package com.crm.business.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.TypeUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.crm.business.admin.service.*;
import com.crm.business.crm.mapper.CrmStudentMapper;
import com.crm.business.crm.service.*;
import com.crm.business.servlet.ApplicationContextHolder;
import com.crm.business.servlet.BaseServiceImpl;
import com.crm.business.utils.*;
import com.crm.common.admin.entity.PO.AdminRole;
import com.crm.common.constant.Constants;
import com.crm.common.core.redis.RedisCache;
import com.crm.common.crm.common.CrmExcelUtil;
import com.crm.common.crm.common.CrmModel;
import com.crm.common.crm.common.ElasticUtil;
import com.crm.common.crm.constant.*;
import com.crm.common.crm.entity.BO.*;
import com.crm.common.crm.entity.PO.*;
import com.crm.common.crm.entity.VO.*;
import com.crm.common.enums.ErrorCodeConstants;
import com.crm.common.exception.CustomException;
import com.crm.common.ka.core.common.Const;
import com.crm.common.ka.core.common.SystemCodeEnum;
import com.crm.common.ka.core.common.log.BehaviorEnum;
import com.crm.common.ka.core.entity.BasePage;
import com.crm.common.ka.core.entity.PageEntity;
import com.crm.common.ka.core.entity.UserInfo;
import com.crm.common.ka.core.exception.CrmException;
import com.crm.common.ka.core.feign.admin.entity.*;
import com.crm.common.ka.core.feign.crm.entity.CrmEventBO;
import com.crm.common.ka.core.feign.crm.entity.QueryEventCrmPageBO;
import com.crm.common.ka.core.feign.crm.entity.SimpleCrmEntity;
import com.crm.common.ka.core.redis.Redis;
import com.crm.common.ka.core.servlet.upload.FileEntity;
import com.crm.common.utils.DateUtils;
import com.crm.common.utils.DesensitizedUtils;
import com.crm.common.utils.spring.SpringUtils;
import com.github.pagehelper.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 客户表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-05-29
 */
@Service(value = "studentService")
@Slf4j
public class CrmStudentServiceImpl extends BaseServiceImpl<CrmStudentMapper, CrmStudent> implements ICrmStudentService, CrmPageService {

    @Autowired
    private ICrmFieldService crmFieldService;

    @Autowired
    private ICrmStudentDataService crmStudentDataService;

    @Autowired
    private ICrmActivityService crmActivityService;

    @Autowired
    private ICrmActionRecordService crmActionRecordService;

    @Autowired
    private ICrmBackLogDealService crmBackLogDealService;

    @Autowired
    private ICrmCustomerSettingService crmCustomerSettingService;

    @Autowired
    private ICrmBusinessService crmBusinessService;

    @Autowired
    private ICrmContactsService crmContactsService;

    @Autowired
    private ICrmContractService crmContractService;

    @Autowired
    private ICrmCustomerUserStarService crmCustomerUserStarService;

    @Autowired
    private ActionRecordUtil actionRecordUtil;


    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private AdminService adminService;

    @Autowired
    private AdminFileService adminFileService;

    @Autowired
    private ICrmCustomerPoolService crmCustomerPoolService;

    @Autowired
    private ICrmCustomerPoolRelationService customerPoolRelationService;

    @Autowired
    private ICrmReceivablesService crmReceivablesService;

    @Autowired
    private IBillCrmStudentPoolService crmStudentPoolService;

    @Autowired
    private ICrmCustomerService crmCustomerService;

    @Autowired
    private ICrmStudentUserStarService crmStudentUserStarService;

    @Autowired
    private ICrmReFundService crmReFundService;

    @Autowired
    private RedisCache redisCache;

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryField(Integer id) {
        CrmModel crmModel = queryById(id, null);
        List<CrmModelFiledVO> vos = crmFieldService.queryField(crmModel);

        //领取时间
        vos.removeIf(field -> field.getFieldName().equals("drawTime"));
        vos.removeIf(field -> field.getFieldName().equals("serialNumber"));

        vos.removeIf(field -> field.getFieldName().equals("leadsCreateName"));
        vos.removeIf(field -> field.getFieldName().equals("leadsCreateTime"));
        vos.removeIf(field -> field.getFieldName().equals("addWechat"));
        vos.removeIf(field -> field.getFieldName().equals("addWechatTime"));
        vos.removeIf(field -> field.getFieldName().equals("signClass"));
        vos.removeIf(field -> field.getFieldName().equals("signClassTime"));

        //表单页面去掉负责人
        vos.removeIf(field -> field.getFieldName().equals("ownerUserId"));
        vos.removeIf(field -> field.getFieldName().equals("leadsUserId"));
        //表单页面去掉VIP成交状态与VIP成交时间
        vos.removeIf(field -> field.getFieldName().equals("vipDealStatus"));
        vos.removeIf(field -> field.getFieldName().equals("vipDealTime"));

        //去除是否重复
        vos.removeIf(field -> field.getFieldName().equals("isRepetition"));
        //负责人所在部门
        vos.removeIf(field -> field.getFieldName().equals("ownerDeptId"));
        vos.removeIf(field -> field.getFieldName().equals("studentStatus"));

        // 还款状态
        vos.removeIf(field -> field.getFieldName().equals("repaymentStatus"));
        vos.removeIf(field -> field.getFieldName().equals("studentPoolId"));

        return vos;
    }

    /**
     * 分页查询
     *
     * @param search
     * @return
     */
    @Override
    public BasePage<Map<String, Object>> queryPageList(CrmSearchBO search) {
        search.setLabel(19);
        if(StringUtil.isNotEmpty(search.getSortField()) && "ownerDeptName".equals(search.getSortField())){
            search.setSortField("ownerDeptId");
        }
        BasePage<Map<String, Object>> basePage = queryList(search);
        Long userId = UserUtil.getUserId();
        List<Integer> starIds = crmStudentUserStarService.starList(userId);
        basePage.getList().forEach(map -> {
            if(ObjectUtil.isNotEmpty(map.get("teacherId"))){
                // 营销讲师名称回显
                Long teacherId = Long.valueOf(String.valueOf(map.get("teacherId")));
                if(ObjectUtil.isNotEmpty(teacherId)){
                    String teacherName = UserCacheUtil.getUserName(teacherId);
                    map.put("teacherName",teacherName);
                }
            }

            // 负责人名称回显
            if(ObjectUtil.isNotEmpty(map.get("ownerUserId"))){
                Long ownerUserId = Long.valueOf(String.valueOf(map.get("ownerUserId")));
                if(ObjectUtil.isNotEmpty(ownerUserId)){
                    String ownerUserName = UserCacheUtil.getUserName(ownerUserId);
                    map.put("ownerUserName",ownerUserName);
                }
            }

            //助教协作人名称回显
            if(ObjectUtil.isNotEmpty(map.get("assistantUserId"))){
                Long assistantUserId = Long.valueOf(String.valueOf(map.get("assistantUserId")));
                if(ObjectUtil.isNotEmpty(assistantUserId)){
                    String assistantUserName = UserCacheUtil.getUserName(assistantUserId);
                    map.put("assistantUserName",assistantUserName);
                }
            }

            //创建人名称回显
            if(ObjectUtil.isNotEmpty(map.get("createUserId"))){
                Long createUserId = Long.valueOf(String.valueOf(map.get("createUserId")));
                if(ObjectUtil.isNotEmpty(createUserId)){
                    String createUserName = UserCacheUtil.getUserName(createUserId);
                    map.put("createUserName",createUserName);
                }
            }


            Integer studentId = (Integer) map.get("studentId");
            map.put("star", starIds.contains((studentId)) ? 1 : 0);
            Integer businessCount = crmBusinessService.lambdaQuery().eq(CrmBusiness::getCustomerId, studentId).eq(CrmBusiness::getStatus, 1).count();
            map.put("businessCount", businessCount);
            //查询联系人,新建合同关联需要
            Object contactsId = map.get("contactsId");
            if (ObjectUtil.isNotEmpty(contactsId)) {
                CrmContacts contacts = crmContactsService.lambdaQuery().select(CrmContacts::getName, CrmContacts::getMobile, CrmContacts::getAddress)
                        .eq(CrmContacts::getContactsId, contactsId).one();
                if (contacts != null) {
                    map.put("contactsName", contacts.getName());
                    map.put("contactsMobile", contacts.getMobile());
                    map.put("contactsAddress", contacts.getAddress());
                }
            }


            //负责人所在部门
            if (ObjectUtil.isNotEmpty(map.get("ownerDeptId"))) {
                Long ownerDeptId = Long.valueOf(String.valueOf(map.get("ownerDeptId")));
                if (ObjectUtil.isNotEmpty(ownerDeptId)) {
                    String ownerDeptName = adminService.queryAllDeptNameByDeptId(Integer.valueOf(ownerDeptId.toString()));
                    map.put("ownerDeptName", ownerDeptName);
                }
            }


        });
        setPoolDay(basePage.getList());
        return basePage;
    }

    /**
     * VIP学员库查询
     * @param search
     * @return
     */
    @Override
    public BasePage<Map<String, Object>> queryPageListForPool(CrmSearchBO search){
        search.setLabel(19);

        // 根据VIP学员池配置查看当前用户是否有权限查看列表数据
        QueryWrapper<BillCrmStudentPool> queryWrapper = new QueryWrapper<BillCrmStudentPool>();
        queryWrapper.eq("status", 1);
        BillCrmStudentPool studentPool = crmStudentPoolService.getBaseMapper().selectOne(queryWrapper);
        List<String> deptIds = Arrays.asList(studentPool.getMemberDeptId().split(","));

        List<Integer> allDeptIds = new ArrayList<>();
        for(String deptId : deptIds){
            allDeptIds.addAll(SpringUtils.getBean(IAdminDeptService.class).queryChildDept(Integer.valueOf(deptId)));
            allDeptIds.add(Integer.valueOf(deptId));
        }

        if((!allDeptIds.contains(UserUtil.getUser().getDeptId())) && (!UserUtil.isAdmin())){
            BasePage<Map<String, Object>> basePage = new BasePage<>();
            basePage.setList(new ArrayList<>());
            basePage.setTotal(0);
            basePage.setCurrent(1);
            return basePage;
        }

        Long studentPoolId = studentPool.getStudentPoolId();
        search.setStudentPoolId(studentPoolId);

        BasePage<Map<String, Object>> basePage = queryList(search);

        for (Map<String, Object> map : basePage.getList()) {
            if (ObjectUtil.isNotEmpty(map.get("telephone"))) {
                String phone = DesensitizedUtils.mobilePhone(map.get("telephone").toString());
                map.put("telephone", phone);
            }
            if(ObjectUtil.isNotEmpty(map.get("wechat"))){
                String wechat = DesensitizedUtils.mobileWechat(map.get("wechat").toString());
                map.put("wechat",wechat);
            }

            if(ObjectUtil.isNotEmpty(map.get("teacherId"))){
                // 营销讲师名称回显
                Long teacherId = Long.valueOf(String.valueOf(map.get("teacherId")));
                if(ObjectUtil.isNotEmpty(teacherId)){
                    String teacherName = UserCacheUtil.getUserName(teacherId);
                    map.put("teacherName",teacherName);
                }
            }

            // 负责人名称回显
            if(ObjectUtil.isNotEmpty(map.get("ownerUserId"))){
                Long ownerUserId = Long.valueOf(String.valueOf(map.get("ownerUserId")));
                if(ObjectUtil.isNotEmpty(ownerUserId)){
                    String ownerUserName = UserCacheUtil.getUserName(ownerUserId);
                    map.put("ownerUserName",ownerUserName);
                }
            }
        }
        return basePage;
    }


    /**
     * 为客户设置距进入公海时间
     *
     * @param list
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @date 2020/10/26 10:16
     **/
    private void setPoolDay(List<Map<String, Object>> list) {
        Long userId = UserUtil.getUserId();
        Date date = new Date();
        List<CrmCustomerPool> poolList = crmCustomerPoolService.lambdaQuery().eq(CrmCustomerPool::getStatus, 1).eq(CrmCustomerPool::getPutInRule, 1).eq(CrmCustomerPool::getRemindSetting, 1).list();
        poolList.forEach(pool -> {
            List<Long> userIdsList = new ArrayList<>();
            List<Integer> deptIds = StrUtil.splitTrim(pool.getMemberDeptId(), Const.SEPARATOR).stream().map(Integer::valueOf).collect(Collectors.toList());
            if (deptIds.size() > 0) {
                userIdsList.addAll(adminService.queryUserByDeptIds(deptIds));
            }
            if (StrUtil.isNotEmpty(pool.getMemberUserId())) {
                userIdsList.addAll(Arrays.stream(pool.getMemberUserId().split(Const.SEPARATOR)).map(Long::parseLong).collect(Collectors.toList()));
            }
            List<CrmCustomerPoolRule> ruleList = SpringUtils.getBean(ICrmCustomerPoolRuleService.class).lambdaQuery().eq(CrmCustomerPoolRule::getPoolId, pool.getPoolId()).list();
            for (CrmCustomerPoolRule rule : ruleList) {
                Integer remindDay = pool.getRemindDay();
                //已成交客户是否进入公海 0不进入 1进入
                Integer dealHandle = rule.getDealHandle();
                //有商机客户是否进入公海 0不进入 1进入
                Integer businessHandle = rule.getBusinessHandle();
                Integer limitDay = rule.getLimitDay();
                //客户级别设置 1全部 2根据级别分别设置
                Integer levelSetting = rule.getCustomerLevelSetting();
                String level = rule.getLevel();
                userIdsList.add(userId);
                for (Map<String, Object> map : list) {
                    //成交状态 0 未成交 1 已成交
                    Integer dealStatus = (Integer) map.get("dealStatus");
                    //商机个数
                    Integer businessCount = (Integer) map.get("businessCount");
                    Long ownerUserId = TypeUtils.castToLong(map.get("ownerUserId"));
                    String customerLevel = (String) map.get("level");
                    //判断负责人
                    if (!userIdsList.contains(ownerUserId)) {
                        continue;
                    }
                    //成交状态
                    if (Objects.equals(dealHandle, 0) && Objects.equals(dealStatus, 1)) {
                        continue;
                    }
                    //商机数量
                    if (Objects.equals(businessHandle, 0) && businessCount > 0) {
                        continue;
                    }
                    //客户级别
                    if (Objects.equals(levelSetting, 2) && !Objects.equals(level, customerLevel)) {
                        continue;
                    }
                    Date receiveTime = map.get("receiveTime") != null ? DateUtil.parse((String) map.get("receiveTime")) : null;
                    if (rule.getType().equals(1)) {
                        //跟进时间
                        Date lastTime = DateUtil.parse((String) map.get("lastTime"));
                        if (lastTime == null) {
                            lastTime = DateUtil.parse((String) map.get("createTime"));
                        }
                        if (receiveTime != null) {
                            lastTime = lastTime.getTime() > receiveTime.getTime() ? lastTime : receiveTime;
                        }
                        setPoolDayForCustomer(lastTime, date, limitDay, levelSetting, map);
                    }
                    if (rule.getType().equals(2)) {
                        setPoolDayForCustomer(receiveTime, date, limitDay, levelSetting, map);
                    }
                    if (rule.getType().equals(3)) {
                        setPoolDayForCustomer(receiveTime, date, limitDay, levelSetting, map);
                    }
                }
            }
        });
    }


    /**
     * 计算客户的距进入公海时间
     *
     * @param startTime
     * @param date
     * @param limitDay
     * @param levelSetting
     * @param map
     * @return void
     * @date 2020/10/26 10:02
     **/
    private static void setPoolDayForCustomer(Date startTime, Date date, Integer limitDay, Integer levelSetting, Map<String, Object> map) {
        if (startTime == null) {
            return;
        }
        long betweenDay = DateUtil.betweenDay(startTime, date, true);
        Integer poolDay = limitDay - (int) betweenDay;
        Integer customerPoolDay = (Integer) map.get("poolDay");
        if (customerPoolDay != null) {
            poolDay = poolDay < customerPoolDay ? poolDay : customerPoolDay;
        }
        poolDay = poolDay > 0 ? poolDay : 0;
        if (Objects.equals(levelSetting, 1)) {
            //所有客户
            map.put("poolDay", poolDay);
        } else if (Objects.equals(levelSetting, 2)) {
            //客户级别
            map.put("poolDay", poolDay);
        }
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public CrmModel queryById(Integer id, Integer poolId) {
        CrmModel crmModel;
        if (id != null) {
            crmModel = getBaseMapper().queryById(id, UserUtil.getUserId());
            crmModel.setLabel(CrmEnum.STUDENT.getType());
            crmModel.setOwnerUserName(UserCacheUtil.getUserName(crmModel.getOwnerUserId()));
            crmStudentDataService.setDataByBatchId(crmModel);
            List<String> stringList = SpringUtils.getBean(ICrmRoleFieldService.class).queryNoAuthField(crmModel.getLabel());
            List<String> deptFieldList = SpringUtils.getBean(ICrmDeptFieldService.class).queryNoAuthField(crmModel.getLabel());
            stringList = stringList.stream().filter(field -> deptFieldList.contains(field)).collect(Collectors.toList());

            stringList = stringList.stream().distinct().collect(Collectors.toList());
            stringList.forEach(crmModel::remove);
            if (ObjectUtil.isNotEmpty(poolId)) {
                LambdaQueryWrapper<CrmCustomerPoolFieldSetting> wrapper = new LambdaQueryWrapper<>();
                wrapper.select(CrmCustomerPoolFieldSetting::getFieldName);
                wrapper.eq(CrmCustomerPoolFieldSetting::getPoolId, poolId).eq(CrmCustomerPoolFieldSetting::getIsHidden, 1);
                List<String> nameList = SpringUtils.getBean(ICrmCustomerPoolFieldSettingService.class).listObjs(wrapper, Object::toString);
                nameList.forEach(crmModel::remove);
                JSONObject poolAuthList = crmCustomerPoolService.queryAuthByPoolId(poolId);
                crmModel.put("poolAuthList", poolAuthList);
            }else{
                Long isPool = (Long) crmModel.get("isPool");
                if (Objects.equals(isPool,1L)){
                    String poolIdStr = baseMapper.queryPoolIdsByCustomer(id);
                    if (StrUtil.isNotEmpty(poolIdStr)){
                        List<String> poolIds = StrUtil.splitTrim(poolIdStr, Const.SEPARATOR);
                        List<Integer> poolIdList = poolIds.stream().map(Integer::valueOf).collect(Collectors.toList());
                        JSONObject poolAuthList = crmCustomerPoolService.getOnePoolAuthByPoolIds(poolIdList);
                        crmModel.put("poolAuthList", poolAuthList);
                    }
                }
            }

            if(BeanUtil.isNotEmpty(crmModel.get("ownerDeptId"))){
                crmModel.put("ownerDeptName", this.adminService.queryDeptName(Integer.valueOf(String.valueOf(crmModel.get("ownerDeptId")))));
            }else{
                Integer deptId = UserCacheUtil.getUserInfo((Long)crmModel.get("ownerUserId")).getDeptId();
                crmModel.put("ownerDeptName", this.adminService.queryDeptName(deptId));
            }

            Integer contactsId = (Integer) crmModel.get("contactsId");
            if (contactsId != null) {
                CrmContacts contacts = crmContactsService.getById(contactsId);
                crmModel.put("contactsName", contacts.getName());
                crmModel.put("contactsMobile", contacts.getMobile());
                crmModel.put("contactsAddress", contacts.getAddress());
            }
        } else {
            crmModel = new CrmModel(CrmEnum.STUDENT.getType());
        }
        return crmModel;
    }

    /**
     * 保存或新增信息
     *
     * @param crmModel model
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> addOrUpdate(CrmModelSaveBO crmModel, boolean isExcel, Integer poolId) {
        CrmStudent crmCustomer = BeanUtil.copyProperties(crmModel.getEntity(), CrmStudent.class);
        if (crmCustomer.getStudentId() != null) {
            if (!UserUtil.isAdmin() && getBaseMapper().queryIsRoUser(crmCustomer.getStudentId(), UserUtil.getUserId()) > 0) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
        }
        String batchId = StrUtil.isNotEmpty(crmCustomer.getBatchId()) ? crmCustomer.getBatchId() : IdUtil.simpleUUID();
        actionRecordUtil.updateRecord(crmModel.getField(), Dict.create().set("batchId", batchId).set("dataTableName", "bill_crm_customer_data"));
        crmStudentDataService.saveData(crmModel.getField(), batchId);
        if (StrUtil.isEmpty(crmCustomer.getEmail())) {
            crmCustomer.setEmail(null);
        }

        if(CollectionUtil.isNotEmpty(crmModel.getField())){
            CrmModel model = new CrmModel();
            //如果是修改 则先查询 线索数据
            if(StrUtil.isNotEmpty(crmCustomer.getBatchId())){
                model = getBaseMapper().queryById(crmCustomer.getStudentId(), UserUtil.getUserId());
                crmStudentDataService.setDataByBatchId(model);
            }

            if(StrUtil.isEmpty(crmCustomer.getBatchId())){
                LocalDate date = LocalDate.now();
                String no = generateNo(date);
                Long longValue;
                if(no.indexOf("KH")!= -1){
                    longValue = Long.valueOf(no.substring(2)) + 1;
                }else{
                    longValue = Long.valueOf(no) + 1;
                }
                no = "KH" + longValue;
                crmCustomer.setSerialNumber(no);
            }

        }
        boolean isUpdate = false;
        CrmStudent student = new CrmStudent();
        if (crmCustomer.getStudentId() != null) {

            // 回款审批中及审批通过不允许编辑客户信息
            Integer receivables = crmReceivablesService.queryCountReceivablesByStudentId(crmCustomer.getStudentId());
            CrmStudent oldCustomer = this.getById(crmCustomer.getStudentId());
            BeanUtils.copyProperties(oldCustomer, student);
            if(receivables > 0){
                if((oldCustomer.getTelephone() == null && crmCustomer.getTelephone() != null) ||
                        (oldCustomer.getTelephone() != null && crmCustomer.getTelephone() == null) ||
                        (StringUtil.isNotEmpty(oldCustomer.getTelephone()) && StringUtil.isNotEmpty(crmCustomer.getTelephone()) && (!crmCustomer.getTelephone().equals(oldCustomer.getTelephone())))){
                    throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_HAVE_RECEIVABLES);
                }
            }

            crmBackLogDealService.deleteByType(crmCustomer.getOwnerUserId(), getLabel(), CrmBackLogEnum.TODAY_CUSTOMER, crmCustomer.getStudentId());
            crmBackLogDealService.deleteByType(crmCustomer.getOwnerUserId(), getLabel(), CrmBackLogEnum.FOLLOW_CUSTOMER, crmCustomer.getStudentId());
            crmCustomer.setUpdateTime(DateUtil.date());
            actionRecordUtil.updateRecord(BeanUtil.beanToMap(getById(crmCustomer.getStudentId())), BeanUtil.beanToMap(crmCustomer), CrmEnum.STUDENT, crmCustomer.getCustomerName(), crmCustomer.getStudentId());
            updateById(crmCustomer);
            crmCustomer = getById(crmCustomer.getStudentId());
            ElasticUtil.batchUpdateEsData(elasticsearchRestTemplate.getClient(), "student", crmCustomer.getStudentId().toString(), crmCustomer.getCustomerName());
        } else {
            crmCustomer.setVipDealStatus("未成交");
            crmCustomer.setCreateTime(DateUtil.date());
            crmCustomer.setUpdateTime(DateUtil.date());
            crmCustomer.setReceiveTime(DateUtil.date());
            crmCustomer.setDrawTime(DateUtil.date());
            crmCustomer.setCreateUserId(UserUtil.getUserId());
            if (!isExcel && crmCustomer.getOwnerUserId() == null) {
                //导入会手动选择负责人,需要判断
                crmCustomer.setOwnerUserId(UserUtil.getUserId());
                crmCustomer.setOwnerDeptId(String.valueOf(UserUtil.getUser().getDeptId()));
            }
            crmCustomer.setBatchId(batchId);
            crmCustomer.setRwUserId(",");
            crmCustomer.setLastTime(new Date());
            crmCustomer.setRoUserId(",");
            crmCustomer.setStatus(1);
            if (crmCustomer.getOwnerUserId() != null) {
                if (!crmCustomerSettingService.queryCustomerSettingNum(1, crmCustomer.getOwnerUserId())) {
                    throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_SETTING_USER_ERROR);
                }
            }

            save(crmCustomer);
            crmActivityService.addActivity(2, CrmActivityEnum.CUSTOMER, crmCustomer.getStudentId(), "");
            actionRecordUtil.addRecord(crmCustomer.getStudentId(), CrmEnum.STUDENT, crmCustomer.getCustomerName());
            if (isExcel && poolId != null) {
                CrmCustomerPoolRelation relation = new CrmCustomerPoolRelation();
                relation.setCustomerId(crmCustomer.getStudentId());
                relation.setPoolId(poolId);
                customerPoolRelationService.save(relation);
            }
        }
        crmModel.setEntity(BeanUtil.beanToMap(crmCustomer));
        if (isExcel && poolId != null) {
            List<CrmCustomerPoolRelation> poolRelations = customerPoolRelationService.lambdaQuery()
                    .select(CrmCustomerPoolRelation::getPoolId)
                    .eq(CrmCustomerPoolRelation::getCustomerId, crmCustomer.getStudentId())
                    .list();
            crmModel.getEntity().put("poolId", poolRelations.stream().map(CrmCustomerPoolRelation::getPoolId).collect(Collectors.toList()));
        }
        savePage(crmModel, crmCustomer.getStudentId(), isExcel);

        if(isUpdate){
            if(!ObjectUtil.equal(crmCustomer.getTeacherId(), student.getTeacherId())){
                String teacherName = UserCacheUtil.getUserName(crmCustomer.getTeacherId());

                if(student.getTeacherId() != null){
                    addMessage(crmCustomer.getCustomerName(),teacherName,student.getTeacherId(),AdminMessageEnum.CRM_CUSTOMER_CHANGE_TEACHER_USER.getType(),crmCustomer.getStudentId());
                }

                if(crmCustomer.getTeacherId() != null){
                    addMessage(crmCustomer.getCustomerName(),teacherName,crmCustomer.getTeacherId(),AdminMessageEnum.CRM_CUSTOMER_CHANGE_TEACHER_USER.getType(),crmCustomer.getStudentId());
                }
            }

            if(!ObjectUtil.equal(crmCustomer.getAssistantUserId(), student.getAssistantUserId())){
                String teacherName = UserCacheUtil.getUserName(crmCustomer.getAssistantUserId());

                if(student.getAssistantUserId() != null){
                    addMessage(crmCustomer.getCustomerName(),teacherName,student.getAssistantUserId(),AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(),crmCustomer.getStudentId());
                }

                if(student.getAssistantUserId() != null){
                    addMessage(crmCustomer.getCustomerName(),teacherName,crmCustomer.getAssistantUserId(),AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(),crmCustomer.getStudentId());
                }
            }

        }

        Map<String, Object> map = new HashMap<>();
        map.put("customerId", crmCustomer.getStudentId());
        map.put("customerName", crmCustomer.getCustomerName());
        return map;
    }

    @Override
    public void setOtherField(Map<String, Object> map) {
        String ownerUserName = UserCacheUtil.getUserName((Long) map.get("ownerUserId"));
        map.put("ownerUserName", ownerUserName);
        String createUserName = UserCacheUtil.getUserName((Long) map.get("createUserId"));
        map.put("createUserName", createUserName);
        String teacherName = UserCacheUtil.getUserName((Long) map.get("teacherId"));
        map.put("teacherName",teacherName);
        if(null != map.get("leadsCreateId") && !"".equals(map.get("leadsCreateId"))){
            String leadsCreateName = UserCacheUtil.getUserName(Long.valueOf(String.valueOf(map.get("leadsCreateId"))));
            map.put("leadsCreateName",leadsCreateName);
        }

        /*if(null != map.get("sellOwnerId") && !"".equals(map.get("sellOwnerId"))){
            Long owner = Long.parseLong(map.get("sellOwnerId").toString());
            String sellOwner = UserCacheUtil.getUserName(owner);
            map.put("sellOwnerName", sellOwner);
        }*/

        if(null != map.get("assistantUserId") && !"".equals(map.get("assistantUserId"))){
            String[] assistantUserId = map.get("assistantUserId").toString().split(",");
            String assistanUserName = "";
            for(int i=0;i<assistantUserId.length;i++){
                Long user = Long.parseLong(assistantUserId[i]);
                String assistanUser = UserCacheUtil.getUserName(user);
                assistanUserName += assistanUser + ",";
            }
            /*Long user = Long.parseLong(map.get("assistantUserId").toString());
            String assistanUser = UserCacheUtil.getUserName(user);*/
            assistanUserName = assistanUserName.substring(0,assistanUserName.length()-1);
            map.put("assistantUserName", assistanUserName);
        }

        String deptName = "";
        if(BeanUtil.isNotEmpty(map.get("ownerDeptId"))){
            deptName = this.adminService.queryDeptName(Integer.valueOf(String.valueOf(map.get("ownerDeptId"))));
        }
        map.put("ownerDeptName",deptName);

//        String assistantUser = UserCacheUtil.getUserName((Long) map.get("assistantUser"));
//        map.put("assistantUser", assistantUser);
    }


    /**
     * 删除客户数据
     *
     * @param ids ids
     */
    @Override
    public void deleteByIds(List<Integer> ids) {
        for (Integer id : ids) {
            if (!UserUtil.isAdmin() && getBaseMapper().queryIsRoUser(id, UserUtil.getUserId()) > 0) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
        }
//        Integer contractNum = crmContractService.lambdaQuery().ne(CrmContract::getCheckStatus,7).in(CrmContract::getStudentId, ids).count();
//        Integer receivablesNum = crmReceivablesService.lambdaQuery().ne(CrmReceivables::getCheckStatus,7).in(CrmReceivables::getStudentId, ids).count();
        Integer refundNum = crmReFundService.lambdaQuery().ne(CrmRefund::getCheckStatus,7).in(CrmRefund::getStudentId, ids).count();
        if (refundNum > 0) {
            throw new CrmException(CrmCodeEnum.CRM_DATA_JOIN_ERROR);
        }
        lambdaUpdate().set(CrmStudent::getUpdateTime, new Date()).set(CrmStudent::getStatus, 3).in(CrmStudent::getStudentId, ids).update();
        LambdaQueryWrapper<CrmStudent> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CrmStudent::getStudentId, ids);
        List<String> batchList = listObjs(wrapper, Object::toString);
        //删除文件
        adminFileService.delete(batchList);
        //删除跟进记录
        crmActivityService.deleteActivityRecord(CrmActivityEnum.CUSTOMER, ids);
        //删除字段操作记录
        crmActionRecordService.deleteActionRecord(CrmEnum.STUDENT, ids);
        //删除自定义字段
        crmStudentDataService.deleteByBatchId(batchList);
        deletePage(ids);

    }


    @Override
    public JSONObject detectionDataCanBeDelete(List<Integer> ids) {
        Integer contactsNum = crmContactsService.lambdaQuery().in(CrmContacts::getCustomerId, ids).count();
        Integer businessNum = crmBusinessService.lambdaQuery().in(CrmBusiness::getCustomerId, ids).eq(CrmBusiness::getStatus, 1).count();
        JSONObject record = new JSONObject();
        record.fluentPut("contactsNum",contactsNum).fluentPut("businessNum",businessNum).fluentPut("isMore",ids.size() > 1);
        return record;
    }

    /**
     * 修改客户负责人
     *
     * @param changOwnerUserBO data
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeOwnerUser(CrmBusinessChangOwnerUserBO changOwnerUserBO) {
        if (!isMaxOwner(changOwnerUserBO.getOwnerUserId(), changOwnerUserBO.getIds())) {
            throw new CrmException(CrmCodeEnum.THE_NUMBER_OF_CUSTOMERS_HAS_REACHED_THE_LIMIT);
        }
        String ownerUserName = UserCacheUtil.getUserName(changOwnerUserBO.getOwnerUserId());
        List<Long> userList = new ArrayList<>();
        if (UserUtil.isAdmin()){
            userList = adminService.queryUserList();
        }else {
            userList.add(UserUtil.getUserId());
            userList.addAll(adminService.queryChildUserId(UserUtil.getUserId()));
        }
        List<Long> finalUserList = userList;
        changOwnerUserBO.getIds().forEach(id -> {
            if (AuthUtil.isRwAuth(id, CrmEnum.STUDENT)) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
            String memberId = "," + changOwnerUserBO.getOwnerUserId() + ",";
            getBaseMapper().deleteMember(memberId, id);
            CrmStudent customer = getById(id);
            Long oldOwnerUserId = customer.getOwnerUserId();
            if (2 == changOwnerUserBO.getTransferType() && !changOwnerUserBO.getOwnerUserId().equals(customer.getOwnerUserId())) {
                if (1 == changOwnerUserBO.getPower()) {
                    customer.setRoUserId(customer.getRoUserId() + customer.getOwnerUserId() + Const.SEPARATOR);
                }
                if (2 == changOwnerUserBO.getPower()) {
                    customer.setRwUserId(customer.getRwUserId() + customer.getOwnerUserId() + Const.SEPARATOR);
                }
                addTermMessage(AdminMessageEnum.CRM_CUSTOMER_USER, customer.getStudentId(), customer.getCustomerName(), customer.getOwnerUserId());
            }
            customer.setOwnerUserId(changOwnerUserBO.getOwnerUserId());
            //判断是否需要修改创建人
            List<Long> userIds = new ArrayList<>();
            userIds.add(Long.valueOf(String.valueOf(changOwnerUserBO.getOwnerUserId())));
            List<AdminRole> roleList = SpringUtils.getBean(AdminService.class).queryRoleListByUserId(userIds);
            customer.setFollowup(0);
            customer.setIsReceive(1);
            customer.setReceiveTime(DateUtil.date());
            updateById(customer);
            actionRecordUtil.addConversionRecord(id, CrmEnum.STUDENT, changOwnerUserBO.getOwnerUserId(), customer.getCustomerName());
            changOwnerUserBO.getChangeType().forEach(type -> {
                switch (type) {
                    case 1: {
                        List<Integer> ids = crmContactsService.lambdaQuery()
                                .select(CrmContacts::getContactsId)
                                .eq(CrmContacts::getCustomerId, id)
                                .in(CrmContacts::getOwnerUserId, finalUserList)
                                .list().stream().map(CrmContacts::getContactsId).collect(Collectors.toList());
                        crmContactsService.changeOwnerUser(ids, changOwnerUserBO.getOwnerUserId());
                        break;
                    }
                    case 2: {
                        List<Integer> ids = crmBusinessService.lambdaQuery()
                                .select(CrmBusiness::getBusinessId)
                                .eq(CrmBusiness::getCustomerId, id)
                                .in(CrmBusiness::getOwnerUserId,finalUserList)
                                .list().stream().map(CrmBusiness::getBusinessId).collect(Collectors.toList());
                        CrmBusinessChangOwnerUserBO changOwnerUser = new CrmBusinessChangOwnerUserBO();
                        changOwnerUser.setPower(changOwnerUserBO.getPower());
                        changOwnerUser.setTransferType(changOwnerUserBO.getTransferType());
                        changOwnerUser.setIds(ids);
                        changOwnerUser.setOwnerUserId(changOwnerUserBO.getOwnerUserId());
                        crmBusinessService.changeOwnerUser(changOwnerUser);
                        break;
                    }
                    case 3: {
                        List<Integer> ids = crmContractService.lambdaQuery()
                                .select(CrmContract::getContractId)
                                .eq(CrmContract::getCustomerId, id)
                                .in(CrmContract::getOwnerUserId,finalUserList)
                                .list().stream().map(CrmContract::getContractId).collect(Collectors.toList());
                        CrmBusinessChangOwnerUserBO changOwnerUser = new CrmBusinessChangOwnerUserBO();
                        changOwnerUser.setTransferType(changOwnerUserBO.getTransferType());
                        changOwnerUser.setPower(changOwnerUserBO.getPower());
                        changOwnerUser.setIds(ids);
                        changOwnerUser.setOwnerUserId(changOwnerUserBO.getOwnerUserId());
                        crmContractService.changeOwnerUser(changOwnerUser);
                        break;
                    }
                    default:
                        break;
                }
            });
            //修改es
            Map<String, Object> map = new HashMap<>();
            map.put("ownerUserId", changOwnerUserBO.getOwnerUserId());
            map.put("ownerUserName", ownerUserName);
            map.put("rwUserId", customer.getRwUserId());
            map.put("roUserId", customer.getRoUserId());
            map.put("followup", 0);
            map.put("isReceive", 1);
            map.put("receiveTime", DateUtil.formatDateTime(new Date()));
            updateField(map, Collections.singletonList(id));
        });
    }

    /**
     * 全部导出
     *
     * @param response resp
     * @param search   搜索对象
     */
    @Override
    public void exportExcel(HttpServletResponse response, CrmSearchBO search) {
        List<Map<String, Object>> dataList = queryPageList(search).getList();
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            List<CrmFieldSortVO> headList = crmFieldService.queryListHead(getLabel().getType());
            headList.forEach(head -> writer.addHeaderAlias(head.getFieldName(), head.getName()));
            writer.merge(headList.size() - 1, "VIP学员信息");
            if (dataList.size() == 0) {
                Map<String, Object> record = new HashMap<>();
                headList.forEach(head -> record.put(head.getFieldName(), ""));
                dataList.add(record);
            }
            dataList.forEach(record -> {
                record.put("dealStatus", Objects.equals(1, record.get("dealStatus")) ? "已成交" : "未成交");
                record.put("status", Objects.equals(1, record.get("status")) ? "未锁定" : "已锁定");
                record.put("studentStatus", ObjectUtil.isEmpty(record.get("studentStatus")) ? null : Objects.equals(1, record.get("studentStatus")) ? "已入学" : "已退学");
            });
            writer.setOnlyAlias(true);
            writer.write(dataList, true);
            writer.setRowHeight(0, 20);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            String fileName = "VIP学员" + DateUtils.dateTimeNow() + ".xls";
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);

            // 新增消息
            addMessage(String.valueOf(dataList.size()),"导出数据" + String.valueOf(dataList.size()) + "条",UserUtil.getUserId(),AdminMessageEnum.CRM_STUDENT_EXPORT.getType(),null);

        } catch (Exception e) {
            log.error("导出客户错误：", e);
        }
    }

    /**
     * 客户放入公海
     *
     * @param poolBO bo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCustomerByIds(CrmCustomerPoolBO poolBO) {
        if (poolBO.getIds().size() == 0) {
            return;
        }
        Long userId = UserUtil.getUserId();
        List<CrmOwnerRecord> ownerRecordList = new ArrayList<>();
        List<CrmCustomerPoolRelation> poolRelationList = new ArrayList<>();
        for (Integer id : poolBO.getIds()) {
            CrmStudent crmCustomer = getById(id);
            if (crmCustomer.getOwnerUserId() == null) {
                continue;
            }
            boolean isUser = StrUtil.splitTrim(crmCustomer.getRoUserId(), Const.SEPARATOR).contains(userId.toString());
            if (isUser) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
            CrmOwnerRecord crmOwnerRecord = new CrmOwnerRecord();
            crmOwnerRecord.setTypeId(id);
            crmOwnerRecord.setType(CrmEnum.CUSTOMER_POOL.getType());
            crmOwnerRecord.setPreOwnerUserId(crmCustomer.getOwnerUserId());
            crmOwnerRecord.setCreateTime(DateUtil.date());
            ownerRecordList.add(crmOwnerRecord);
            lambdaUpdate()
                    .set(CrmStudent::getOwnerUserId, null)
                    .set(CrmStudent::getPreOwnerUserId, userId)
                    .set(CrmStudent::getPoolTime, new Date())
                    .set(CrmStudent::getIsReceive, null)
                    .set(CrmStudent::getRoUserId, ",")
                    .set(CrmStudent::getRwUserId, ",")
                    .eq(CrmStudent::getStudentId, crmCustomer.getStudentId()).update();
            CrmCustomerPoolRelation relation = new CrmCustomerPoolRelation();
            relation.setCustomerId(id);
            relation.setPoolId(poolBO.getPoolId());
            poolRelationList.add(relation);
            actionRecordUtil.addPutIntoTheOpenSeaRecord(id, getLabel(), crmCustomer.getCustomerName());
        }
        if (ownerRecordList.size() > 0) {
            SpringUtils.getBean(ICrmOwnerRecordService.class).saveBatch(ownerRecordList);
        }
        if (poolRelationList.size() > 0) {
            customerPoolRelationService.saveBatch(poolRelationList);
        }
        LambdaUpdateWrapper<CrmContacts> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(CrmContacts::getOwnerUserId, null);
        wrapper.in(CrmContacts::getCustomerId, poolBO.getIds());
        crmContactsService.update(wrapper);
        putInPool(poolBO);
    }

    /**
     * 标星
     *
     * @param customerId 客户id
     */
    @Override
    public void star(Integer customerId) {
        LambdaQueryWrapper<CrmStudentUserStar> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrmStudentUserStar::getStudentId, customerId);
        wrapper.eq(CrmStudentUserStar::getUserId, UserUtil.getUserId());
        CrmStudentUserStar star = crmStudentUserStarService.getOne(wrapper);
        if (star == null) {
            star = new CrmStudentUserStar();
            star.setStudentId(customerId);
            star.setUserId(UserUtil.getUserId());
            crmStudentUserStarService.save(star);
        } else {
            crmStudentUserStarService.removeById(star.getId());
        }
    }

    /**
     * 设置首要联系人
     *
     * @param contactsBO data
     */
    @Override
    public void setContacts(CrmFirstContactsBO contactsBO) {
        lambdaUpdate().set(CrmStudent::getContactsId, contactsBO.getContactsId())
                .eq(CrmStudent::getStudentId, contactsBO.getCustomerId()).update();
    }

    /**
     * 获取团队成员
     *
     * @param customerId 客户ID
     * @return data
     */
    @Override
    public List<CrmMembersSelectVO> getMembers(Integer customerId) {
        CrmStudent crmCustomer = getById(customerId);
        List<CrmMembersSelectVO> recordList = new ArrayList<>();
        if (crmCustomer.getOwnerUserId() != null) {
            UserInfo userInfo = UserCacheUtil.getUserInfo(crmCustomer.getOwnerUserId());
            CrmMembersSelectVO crmMembersVO = new CrmMembersSelectVO();
            crmMembersVO.setUserId(userInfo.getUserId());
            crmMembersVO.setDeptName(UserCacheUtil.getDeptName(userInfo.getDeptId()));
            crmMembersVO.setRealname(UserCacheUtil.getUserName(userInfo.getUserId()));
            crmMembersVO.setPost(userInfo.getPost());
            crmMembersVO.setPower("负责人权限");
            crmMembersVO.setGroupRole("负责人");
            recordList.add(crmMembersVO);
        }
        String roUserId = crmCustomer.getRoUserId();
        String rwUserId = crmCustomer.getRwUserId();
        String memberIds = roUserId + rwUserId.substring(1);
        if (Const.SEPARATOR.equals(memberIds)) {
            return recordList;
        }
        String[] memberIdsArr = memberIds.substring(1, memberIds.length() - 1).split(",");
        Set<String> memberIdsSet = new HashSet<>(Arrays.asList(memberIdsArr));
        for (String memberId : memberIdsSet) {
            UserInfo userInfo = UserCacheUtil.getUserInfo(Long.valueOf(memberId));
            CrmMembersSelectVO crmMembersVO = new CrmMembersSelectVO();
            crmMembersVO.setUserId(userInfo.getUserId());
            crmMembersVO.setDeptName(UserCacheUtil.getDeptName(userInfo.getDeptId()));
            crmMembersVO.setRealname(UserCacheUtil.getUserName(userInfo.getUserId()));
            crmMembersVO.setGroupRole("普通成员");
            if (roUserId.contains(memberId)) {
                crmMembersVO.setPower("只读");
            } else if (rwUserId.contains(memberId)) {
                crmMembersVO.setPower("读写");
            }
            crmMembersVO.setPost(userInfo.getPost());
            recordList.add(crmMembersVO);
        }
        return recordList;
    }

    /**
     * 领取或分配客户
     *
     * @param poolBO    bo
     * @param isReceive 领取还是分配
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void getCustomersByIds(CrmCustomerPoolBO poolBO, Integer isReceive) {
        if (poolBO.getIds().size() == 0) {
            return;
        }
        if (poolBO.getUserId() == null) {
            poolBO.setUserId(UserUtil.getUserId());
        }
        if (AuthUtil.isPoolAdmin(poolBO.getPoolId()) && isReceive == 1) {
            throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_POOL_DISTRIBUTE_ERROR);
        }
        if (!isMaxOwner(poolBO.getUserId(), poolBO.getIds())) {
            throw new CrmException(CrmCodeEnum.THE_NUMBER_OF_CUSTOMERS_HAS_REACHED_THE_LIMIT);
        }
        CrmCustomerPool pool = crmCustomerPoolService.getById(poolBO.getPoolId());
        if (isReceive == 2) {
            if (pool.getReceiveSetting() != null && pool.getReceiveSetting() == 1) {
                if (poolBO.getIds().size() > pool.getReceiveNum()) {
                    throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_POOL_RECEIVE_ERROR);
                }
                Redis redis = BaseUtil.getRedis();
                String key = "receiveNum:poolId_" + poolBO.getPoolId() + ":userId_" + poolBO.getUserId();
                Integer num = redis.get(key);
                if (ObjectUtil.isNotEmpty(num) && (num + poolBO.getIds().size() > pool.getReceiveNum())) {
                    throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_POOL_RECEIVE_NUMBER_ERROR);
                }
                long expireTime = (DateUtil.endOfDay(DateUtil.date()).getTime() - System.currentTimeMillis()) / 1000;
                redis.setex(key, (int) expireTime, ObjectUtil.isEmpty(num) ? poolBO.getIds().size() : num + poolBO.getIds().size());
            }
        }
        List<CrmOwnerRecord> records = new ArrayList<>();
        for (Integer id : poolBO.getIds()) {
            CrmStudent customer = query().select("student_id", "customer_name").eq("student_id", id).one();
            actionRecordUtil.addDistributionRecord(id, CrmEnum.STUDENT, isReceive.equals(1) ? poolBO.getUserId() : null, customer.getCustomerName());
            //前负责人领取限制，从前负责人脱手开始计算天数
            if (isReceive == 2) {
                if (pool.getPreOwnerSetting() == 1) {
                    Integer days = getBaseMapper().queryOutDays(id, poolBO.getUserId());
                    if (days != null && days <= pool.getPreOwnerSettingDay()) {
                        throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_POOL_PRE_USER_RECEIVE_ERROR);
                    }
                }
            }
            CrmOwnerRecord crmOwnerRecord = new CrmOwnerRecord();
            crmOwnerRecord.setTypeId(id);
            crmOwnerRecord.setType(CrmEnum.CUSTOMER_POOL.getType());
            crmOwnerRecord.setPostOwnerUserId(poolBO.getUserId());
            crmOwnerRecord.setCreateTime(DateUtil.date());
            records.add(crmOwnerRecord);
        }
        SpringUtils.getBean(ICrmOwnerRecordService.class).saveBatch(records);
        LambdaQueryWrapper<CrmCustomerPoolRelation> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CrmCustomerPoolRelation::getCustomerId, poolBO.getIds());
        customerPoolRelationService.remove(wrapper);
        List<Integer> contactsIds = crmContactsService.lambdaQuery().select(CrmContacts::getContactsId).in(CrmContacts::getCustomerId, poolBO.getIds()).list()
                .stream().map(CrmContacts::getContactsId).collect(Collectors.toList());
        crmContactsService.lambdaUpdate().set(CrmContacts::getOwnerUserId, poolBO.getUserId()).in(CrmContacts::getCustomerId, poolBO.getIds()).update();
        lambdaUpdate()
                .set(CrmStudent::getOwnerUserId, poolBO.getUserId())
                .set(CrmStudent::getFollowup, 0)
                .set(CrmStudent::getReceiveTime, new Date())
                .set(CrmStudent::getUpdateTime, new Date())
                .set(CrmStudent::getIsReceive, isReceive)
                .in(CrmStudent::getStudentId, poolBO.getIds())
                .update();
        receiveCustomer(poolBO, isReceive, contactsIds);
    }

    /**
     * 添加团队成员
     *
     * @param crmMemberSaveBO data
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addMember(CrmMemberSaveBO crmMemberSaveBO) {
        for (Integer id : crmMemberSaveBO.getIds()) {
            if (AuthUtil.isCrmOperateAuth(CrmEnum.STUDENT, id)) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
            CrmStudent oldCustomer = lambdaQuery().eq(CrmStudent::getStudentId,id).ne(CrmStudent::getStatus,3).one();
            if (oldCustomer == null){
                continue;
            }
            Long ownerUserId = oldCustomer.getOwnerUserId();
            for (Long memberId : crmMemberSaveBO.getMemberIds()) {
                if (ownerUserId.equals(memberId)) {
                    throw new CrmException(CrmCodeEnum.CRM_MEMBER_ADD_ERROR);
                }
                oldCustomer.setRoUserId(oldCustomer.getRoUserId().replace(Const.SEPARATOR + memberId.toString() + Const.SEPARATOR, Const.SEPARATOR));
                oldCustomer.setRwUserId(oldCustomer.getRwUserId().replace(Const.SEPARATOR + memberId.toString() + Const.SEPARATOR, Const.SEPARATOR));
                String name = lambdaQuery().select(CrmStudent::getCustomerName).eq(CrmStudent::getStudentId, id).one().getCustomerName();
                addTermMessage(AdminMessageEnum.CRM_CUSTOMER_USER, oldCustomer.getStudentId(), oldCustomer.getCustomerName(), memberId);
                actionRecordUtil.addMemberActionRecord(CrmEnum.STUDENT, id, memberId, name);
            }
            if (1 == crmMemberSaveBO.getPower()) {
                oldCustomer.setRoUserId(oldCustomer.getRoUserId() + StrUtil.join(Const.SEPARATOR, crmMemberSaveBO.getMemberIds()) + Const.SEPARATOR);
            } else if (2 == crmMemberSaveBO.getPower()) {
                oldCustomer.setRwUserId(oldCustomer.getRwUserId() + StrUtil.join(Const.SEPARATOR, crmMemberSaveBO.getMemberIds()) + Const.SEPARATOR);
            }
            updateById(oldCustomer);
            Map<String, Object> map = new HashMap<>();
            map.put("roUserId", oldCustomer.getRoUserId());
            map.put("rwUserId", oldCustomer.getRwUserId());
            updateField(map, Collections.singletonList(id));
            if (CollUtil.isNotEmpty(crmMemberSaveBO.getChangeType())) {
                if (crmMemberSaveBO.getChangeType().contains(2)) {
                    List<Integer> ids = crmBusinessService.lambdaQuery()
                            .select(CrmBusiness::getBusinessId)
                            .eq(CrmBusiness::getCustomerId, id)
                            .list().stream().map(CrmBusiness::getBusinessId).collect(Collectors.toList());
                    crmMemberSaveBO.setIds(ids);
                    crmBusinessService.addMember(crmMemberSaveBO);
                }
                if (crmMemberSaveBO.getChangeType().contains(3)) {
                    List<Integer> ids = crmContractService.lambdaQuery()
                            .select(CrmContract::getContractId)
                            .eq(CrmContract::getCustomerId, id)
                            .list().stream().map(CrmContract::getContractId).collect(Collectors.toList());
                    crmMemberSaveBO.setIds(ids);
                    crmContractService.addMember(crmMemberSaveBO);
                }
            }
        }

    }

    /**
     * 删除团队成员
     *
     * @param crmMemberSaveBO data
     */
    @Override
    public void deleteMember(CrmMemberSaveBO crmMemberSaveBO) {
        for (Integer id : crmMemberSaveBO.getIds()) {
            if (AuthUtil.isCrmOperateAuth(CrmEnum.STUDENT, id)) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
            deleteMembers(id, crmMemberSaveBO.getMemberIds());
        }
    }


    private void deleteMembers(Integer id, List<Long> memberIds) {
        CrmStudent oldCustomer = getById(id);
        Long ownerUserId = oldCustomer.getOwnerUserId();
        for (Long memberId : memberIds) {
            if (ownerUserId.equals(memberId)) {
                throw new CrmException(CrmCodeEnum.CRM_MEMBER_DELETE_ERROR);
            }
            oldCustomer.setRoUserId(oldCustomer.getRoUserId().replace(Const.SEPARATOR + memberId.toString() + Const.SEPARATOR, Const.SEPARATOR));
            oldCustomer.setRwUserId(oldCustomer.getRwUserId().replace(Const.SEPARATOR + memberId.toString() + Const.SEPARATOR, Const.SEPARATOR));
            if (!memberId.equals(UserUtil.getUserId())) {
                addTermMessage(AdminMessageEnum.CRM_CUSTOMER_REMOVE_TEAM, oldCustomer.getStudentId(), oldCustomer.getCustomerName(), memberId);
                actionRecordUtil.addDeleteMemberActionRecord(CrmEnum.STUDENT, id, memberId, false, oldCustomer.getCustomerName());
            } else {
                addTermMessage(AdminMessageEnum.CRM_CUSTOMER_TEAM_EXIT, oldCustomer.getStudentId(), oldCustomer.getCustomerName(), oldCustomer.getOwnerUserId());
                actionRecordUtil.addDeleteMemberActionRecord(CrmEnum.STUDENT, id, memberId, true, oldCustomer.getCustomerName());
            }
        }
        updateById(oldCustomer);
        Map<String, Object> map = new HashMap<>();
        map.put("roUserId", oldCustomer.getRoUserId());
        map.put("rwUserId", oldCustomer.getRwUserId());
        updateField(map, Collections.singletonList(id));
    }

    /**
     * 退出团队
     *
     * @param customerId 客户ID
     */
    @Override
    public void exitTeam(Integer customerId) {
        deleteMembers(customerId, Collections.singletonList(UserUtil.getUserId()));
    }

    /**
     * 下载导入模板
     *
     * @param response resp
     * @throws IOException ex
     */
    @Override
    public void downloadExcel(HttpServletResponse response) throws IOException {
        List<CrmModelFiledVO> crmModelFiledList = queryField(null);
        crmModelFiledList.removeIf(model -> Arrays.asList(FieldEnum.FILE, FieldEnum.CHECKBOX, FieldEnum.USER, FieldEnum.STRUCTURE, FieldEnum.SINGLE_USER).contains(FieldEnum.parse(model.getType())));
        crmModelFiledList.removeIf(model -> "ownerSeas".equals(model.getFieldName()));
        crmModelFiledList.removeIf(model -> "source".equals(model.getFieldName()));
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("VIP学员导入表");
        sheet.setDefaultRowHeight((short) 400);
        CellStyle textStyle = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        textStyle.setDataFormat(format.getFormat("@"));
        for (int i = 0; i < crmModelFiledList.size(); i++) {
            if (crmModelFiledList.size() > i && Objects.equals(crmModelFiledList.get(i).getType(), FieldEnum.DATE.getType())) {
                CellStyle dateStyle = wb.createCellStyle();
                DataFormat dateFormat = wb.createDataFormat();
                dateStyle.setDataFormat(dateFormat.getFormat(DatePattern.NORM_DATE_PATTERN));
                sheet.setDefaultColumnStyle(i, dateStyle);
            } else if (crmModelFiledList.size() > i && Objects.equals(crmModelFiledList.get(i).getType(), FieldEnum.DATETIME.getType())) {
                CellStyle dateStyle = wb.createCellStyle();
                DataFormat dateFormat = wb.createDataFormat();
                dateStyle.setDataFormat(dateFormat.getFormat(DatePattern.NORM_DATETIME_PATTERN));
                sheet.setDefaultColumnStyle(i, dateStyle);
            } else {
                sheet.setDefaultColumnStyle(i, textStyle);
            }
            sheet.setColumnWidth(i, 20 * 256);
        }
        HSSFRow titleRow = sheet.createRow(0);
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = wb.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 16);
        cellStyle.setFont(font);
        titleRow.createCell(0).setCellValue("VIP学员导入模板(*)为必填项-通过微信号/手机号匹配");
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        titleRow.getCell(0).setCellStyle(cellStyle);
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, crmModelFiledList.size() - 1);
        sheet.addMergedRegion(region);
        try {
            HSSFRow row = sheet.createRow(1);
            for (int i = 0; i < crmModelFiledList.size(); i++) {
                CrmModelFiledVO record = crmModelFiledList.get(i);
                String fieldName = "_" + record.getFieldName();
                fieldName = fieldName.replaceAll("[\\n`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。， 、？]", "");
                //省市区需特殊处理
                if ("_mapAddress".equals(fieldName)) {
                    HSSFCell cell1 = row.createCell(i);
                    cell1.setCellValue("省");
                    HSSFCell cell2 = row.createCell(i + 1);
                    cell2.setCellValue("市");
                    HSSFCell cell3 = row.createCell(i + 2);
                    cell3.setCellValue("区");
                    HSSFSheet hideSheet = wb.createSheet(fieldName);
                    wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
                    int rowId = 0;
                    // 设置第一行，存省的信息
                    Row provinceRow = hideSheet.createRow(rowId++);
                    provinceRow.createCell(0).setCellValue("省列表");
                    List<String> provinceList = getBaseMapper().queryCityList(100000);
                    for (int x = 0; x < provinceList.size(); x++) {
                        Cell provinceCell = provinceRow.createCell(x + 1);
                        provinceCell.setCellValue(provinceList.get(x));
                    }
                    // 将具体的数据写入到每一行中，行开头为父级区域，后面是子区域。
                    Map<String, List<String>> areaMap = CrmExcelUtil.getAreaMap();
                    for (String key : areaMap.keySet()) {
                        List<String> son = areaMap.get(key);
                        Row subRow = hideSheet.createRow(rowId++);
                        subRow.createCell(0).setCellValue(key);
                        for (int x = 0; x < son.size(); x++) {
                            Cell cell = subRow.createCell(x + 1);
                            cell.setCellValue(son.get(x));
                        }
                        // 添加名称管理器
                        String range = CrmExcelUtil.getRange(1, rowId, son.size());
                        Name name = wb.createName();
                        // key不可重复
                        name.setNameName(key);
                        String formula = fieldName + "!" + range;
                        name.setRefersToFormula(formula);
                    }
                    // 省级下拉框
                    CellRangeAddressList provRangeAddressList = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                    String[] arr = provinceList.toArray(new String[]{});
                    DVConstraint provConstraint = DVConstraint.createExplicitListConstraint(arr);
                    HSSFDataValidation provinceDataValidation = new HSSFDataValidation(provRangeAddressList, provConstraint);
                    provinceDataValidation.createErrorBox("error", "请选择正确的省份");
                    sheet.addValidationData(provinceDataValidation);
                    //市 区下拉框
                    for (int x = 2; x < 10000; x++) {
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 1), sheet, x, i + 1);
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 2), sheet, x, i + 2);
                    }
                } else {
                    HSSFCell cell = row.createCell(i);
                    String cellValue = record.getName() + (record.getIsNull() == 1 ? "(*)" : "");
                    if(FieldEnum.LEVEL_LINKAGE.getType().equals(record.getType())){
                        cellValue = cellValue + "(每级之间请用“|”分割)";
                    }
                    cell.setCellValue(cellValue);
                    List<String> setting = record.getSetting().stream().map(Object::toString).collect(Collectors.toList());
                    if (setting != null && setting.size() != 0) {
                        HSSFSheet hidden = wb.createSheet(fieldName);
                        HSSFCell sheetCell = null;
                        for (int j = 0, length = setting.size(); j < length; j++) {
                            String name = setting.get(j);
                            HSSFRow sheetRow = hidden.createRow(j);
                            sheetCell = sheetRow.createCell(0);
                            sheetCell.setCellValue(name);
                        }
                        Name namedCell = wb.createName();
                        namedCell.setNameName(fieldName);
                        namedCell.setRefersToFormula(fieldName + "!$A$1:$A$" + setting.size());
                        CellRangeAddressList regions = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                        DVConstraint constraint = DVConstraint.createFormulaListConstraint(fieldName);
                        HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
                        wb.setSheetHidden(wb.getSheetIndex(hidden), true);
                        sheet.addValidationData(dataValidation);
                    }
                }
            }
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=customer_import.xls");
            wb.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("error", e);
        } finally {
            wb.close();
        }
    }

    /**
     * 保存客户规则设置
     *
     * @param customerSetting setting
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void customerSetting(CrmCustomerSetting customerSetting) {
        ICrmCustomerSettingUserService settingUserService = SpringUtils.getBean(ICrmCustomerSettingUserService.class);
        settingUserService.removeByMap(new JSONObject().fluentPut("setting_id", customerSetting.getSettingId()));
        customerSetting.setCreateTime(DateUtil.date());
        crmCustomerSettingService.saveOrUpdate(customerSetting);
        Integer type = customerSetting.getType();
        List<Integer> settingIds = crmCustomerSettingService.lambdaQuery()
                .select(CrmCustomerSetting::getSettingId)
                .eq(CrmCustomerSetting::getType, type).list()
                .stream().map(CrmCustomerSetting::getSettingId).collect(Collectors.toList());
        List<CrmCustomerSettingUser> userList = new ArrayList<>();
        for (SimpleDept dept : customerSetting.getDeptIds()) {
            Integer count = settingUserService.lambdaQuery()
                    .eq(CrmCustomerSettingUser::getDeptId, dept.getId())
                    .eq(CrmCustomerSettingUser::getType, 2)
                    .in(CrmCustomerSettingUser::getSettingId, settingIds).count();
            if (count > 0) {
                throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_SETTING_USER_EXIST_ERROR);
            }
            CrmCustomerSettingUser crmCustomerSettingUser = new CrmCustomerSettingUser();
            crmCustomerSettingUser.setDeptId(dept.getId());
            crmCustomerSettingUser.setSettingId(customerSetting.getSettingId());
            crmCustomerSettingUser.setType(2);
            userList.add(crmCustomerSettingUser);
        }
        for (SimpleUser user : customerSetting.getUserIds()) {
            Integer count = settingUserService.lambdaQuery()
                    .eq(CrmCustomerSettingUser::getUserId, user.getUserId())
                    .eq(CrmCustomerSettingUser::getType, 1)
                    .in(CrmCustomerSettingUser::getSettingId, settingIds).count();
            if (count > 0) {
                throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_SETTING_USER_EXIST_ERROR);
            }
            CrmCustomerSettingUser crmCustomerSettingUser = new CrmCustomerSettingUser();
            crmCustomerSettingUser.setUserId(user.getUserId());
            crmCustomerSettingUser.setSettingId(customerSetting.getSettingId());
            crmCustomerSettingUser.setType(1);
            userList.add(crmCustomerSettingUser);
        }
        settingUserService.saveBatch(userList);
    }

    /**
     * 删除客户规则设置
     *
     * @param settingId settingId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCustomerSetting(Integer settingId) {
        CrmCustomerSetting setting = crmCustomerSettingService.getById(settingId);
        if (setting != null) {
            ICrmCustomerSettingUserService settingUserService = SpringUtils.getBean(ICrmCustomerSettingUserService.class);
            settingUserService.removeByMap(new JSONObject().fluentPut("setting_id", settingId));
            crmCustomerSettingService.removeById(settingId);
        }
    }

    @Override
    public List<CrmModelFiledVO> information(Integer customerId, Integer poolId) {
        CrmModel crmModel = queryById(customerId, null);
        Set<String> set  = crmModel.keySet();
        List<String> keyList = new ArrayList<>(set);

//        List<String> keyList = Arrays.asList("customerName", "trainingPeriods", "nextTime", "website", "remark", "telephone", "mobile", "email", "lastTime", "updateTime", "createTime","assistantUserId","teacherId");
        List<String> systemFieldList = Arrays.asList("serialNumber","lastTime","studentStatus","repaymentStatus","leadsUserId","leadsCreateId","leadsCreateTime",
                "drawTime","ownerDeptId","createUserName", "createTime", "updateTime", "lastContent", "vipDealStatus","vipDealTime", "receiveTime");

        List<CrmModelFiledVO> crmModelFiledVOS = queryInformation(crmModel, keyList);

        crmModelFiledVOS.removeIf(item -> "ownerDeptId".equals(item.getFieldName()));
        crmModelFiledVOS.add(new CrmModelFiledVO().setFieldName("ownerDeptId").setName("负责人所在部门").setValue(new JSONObject().fluentPut("ownerDeptId", crmModel.get("ownerDeptId")).fluentPut("ownerDeptName", crmModel.get("ownerDeptName"))).setAuthLevel(2).setFieldType(1));

        List<CrmModelFiledVO> collect = crmModelFiledVOS.stream().sorted(Comparator.comparingInt(r -> -r.getFieldType())).peek(r -> {
            if(FieldEnum.SELECT.getType().equals(r.getType())){
                if (CollUtil.isEmpty(r.getSetting())) {
                    r.setSetting(new ArrayList<>(StrUtil.splitTrim(r.getOptions(), Const.SEPARATOR)));
                }
            }
            if (systemFieldList.contains(r.getFieldName())) {
                r.setAuthLevel(2);
                r.setSysInformation(1);
            } else {
                r.setSysInformation(0);
            }

            if("ownerUserId".equals(r.getFieldName())){
                r.setAuthLevel(2);
            }
        }).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(poolId)) {
            LambdaQueryWrapper<CrmCustomerPoolFieldSetting> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmCustomerPoolFieldSetting::getName, CrmCustomerPoolFieldSetting::getIsHidden);
            wrapper.eq(CrmCustomerPoolFieldSetting::getPoolId, poolId);
            List<CrmCustomerPoolFieldSetting> fieldSettings = SpringUtils.getBean(ICrmCustomerPoolFieldSettingService.class).list(wrapper);
            List<String> nameList = fieldSettings.stream().filter(setting -> setting.getIsHidden().equals(1)).map(CrmCustomerPoolFieldSetting::getName).collect(Collectors.toList());
            //查询新增的自定义字段并且公海还没有进行设置的字段名称
            List<String> collect1 = collect.stream().map(CrmModelFiledVO::getName).collect(Collectors.toList());
            List<String> collect2 = fieldSettings.stream().map(CrmCustomerPoolFieldSetting::getName).collect(Collectors.toList());
            Collection<String> disjunction = CollUtil.disjunction(collect1, collect2);
            collect.removeIf(r -> disjunction.contains(r.getName()) || nameList.contains(r.getName()) || "负责人".equals(r.getName()) || "负责人获取客户时间".equals(r.getName()));
        } else {
            collect.removeIf(r -> "前负责人".equals(r.getName()));
        }

        return collect;
    }

    /**
     * 查询客户规则设置
     *
     * @param pageEntity entity
     * @param type       type
     */
    @Override
    public BasePage<CrmCustomerSetting> queryCustomerSetting(PageEntity pageEntity, Integer type) {
        BasePage<CrmCustomerSetting> page = crmCustomerSettingService.lambdaQuery().eq(CrmCustomerSetting::getType, type).page(pageEntity.parse());
        ICrmCustomerSettingUserService settingUserService = SpringUtils.getBean(ICrmCustomerSettingUserService.class);
        page.getList().forEach(crmCustomerSetting -> {
            List<CrmCustomerSettingUser> list = settingUserService.lambdaQuery().eq(CrmCustomerSettingUser::getSettingId, crmCustomerSetting.getSettingId()).list();
            List<Integer> deptIds = new ArrayList<>();
            List<Long> userIds = new ArrayList<>();
            list.forEach(settingUser -> {
                if (settingUser.getType().equals(1)) {
                    userIds.add(settingUser.getUserId());
                } else if (settingUser.getType().equals(2)) {
                    deptIds.add(settingUser.getDeptId());
                }
            });
            if (userIds.size() > 0) {
                List<SimpleUser> data = adminService.queryUserByIds(userIds);
                crmCustomerSetting.setUserIds(data);
                crmCustomerSetting.setRange(data.stream().map(SimpleUser::getRealname).collect(Collectors.joining(Const.SEPARATOR)));
            } else {
                crmCustomerSetting.setUserIds(new ArrayList<>());
            }

            if (deptIds.size() > 0) {
                List<SimpleDept> data = adminService.queryDeptByIds(deptIds);
                crmCustomerSetting.setDeptIds(data);
                String range = crmCustomerSetting.getRange();
                if (StrUtil.isNotEmpty(range)) {
                    range = range + Const.SEPARATOR;
                } else {
                    range = "";
                }
                range = range + data.stream().map(SimpleDept::getName).collect(Collectors.joining(Const.SEPARATOR));
                crmCustomerSetting.setRange(range);
            } else {
                crmCustomerSetting.setDeptIds(new ArrayList<>());
            }
        });
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setDealStatus(Integer dealStatus, List<Integer> ids) {
        /*BulkRequest bulkRequest = new BulkRequest();
        String index = CrmEnum.STUDENT.getIndex();
        for (Integer id : ids) {
            if (!UserUtil.getUserId().equals(UserUtil.getSuperUser()) && !UserUtil.getUser().getRoles().contains(UserUtil.getSuperRole())
                    && getBaseMapper().queryIsRoUser(id, UserUtil.getUserId()) > 0) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
            CrmCustomer byId = getById(id);
            if (byId != null) {
                byId.setDealStatus(dealStatus);
                byId.setDealTime(new Date());
                updateById(byId);
                UpdateRequest updateRequest = new UpdateRequest(index, "_doc", id.toString());
                Map<String, Object> map = new HashMap<>();
                map.put("dealTime", DateUtil.formatDateTime(new Date()));
                map.put("dealStatus", dealStatus);
                updateRequest.doc(map);
                bulkRequest.add(updateRequest);
            }
        }
        try {
            elasticsearchRestTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
            elasticsearchRestTemplate.refresh(index);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
    }

    @Override
    public BasePage<CrmContacts> queryContacts(CrmContactsPageBO pageEntity) {
        BasePage<CrmContacts> contactsBasePage = pageEntity.parse();
        String conditions = AuthUtil.getCrmAuthSql(CrmEnum.CONTACTS, 1);
        return getBaseMapper().queryContacts(contactsBasePage, pageEntity.getCustomerId(), pageEntity.getSearch(), conditions);
    }

    @Autowired
    private ICrmBusinessTypeService businessTypeService;

    @Override
    public BasePage<Map<String, Object>> queryBusiness(CrmContactsPageBO pageEntity) {
        BasePage<Map<String, Object>> basePage = pageEntity.parse();
        String condition = AuthUtil.getCrmAuthSql(CrmEnum.BUSINESS, "a", 1);
        BasePage<Map<String, Object>> page = getBaseMapper().queryBusiness(basePage, pageEntity.getCustomerId(), pageEntity.getSearch(), condition);
        for (Map<String, Object> map : page.getList()) {
            CrmListBusinessStatusVO crmListBusinessStatusVO = businessTypeService.queryListBusinessStatus((Integer) map.get("typeId"), (Integer) map.get("statusId"), (Integer) map.get("isEnd"));
            map.put("businessStatusCount", crmListBusinessStatusVO);
        }
        return page;
    }

    @Override
    public BasePage<Map<String, Object>> queryContract(CrmContactsPageBO pageEntity) {
        BasePage<Map<String, Object>> basePage = pageEntity.parse();
        String conditions = AuthUtil.getCrmAuthSql(CrmEnum.CONTRACT, "a", 1);
        BasePage<Map<String, Object>> page = getBaseMapper().queryContract(basePage, pageEntity.getCustomerId(), pageEntity.getSearch(), pageEntity.getCheckStatus(), conditions);
        for (Map<String, Object> map : page.getList()) {
            Double contractMoney = map.get("money") != null ? Double.parseDouble(map.get("money").toString()) : 0D;
            BigDecimal receivedProgress = new BigDecimal(100);
            if (!(contractMoney.intValue() == 0)) {
                receivedProgress = ((map.get("receivedMoney") != null ? (BigDecimal) map.get("receivedMoney") : new BigDecimal(0)).divide(new BigDecimal(contractMoney), 4, BigDecimal.ROUND_HALF_UP)).multiply(new BigDecimal(100));
            }
            map.put("receivedProgress", receivedProgress);
        }
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void lock(Integer status, List<String> ids) {
        if (status != 1 && status != 2) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }

        for (String id : ids) {
            if (!UserUtil.isAdmin() && getBaseMapper().queryIsRoUser(Integer.parseInt(id), UserUtil.getUserId()) > 0) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
        }
        if (status == 2) {
            QueryWrapper<CrmStudent> wrapper = new QueryWrapper<>();
            wrapper.select("count(owner_user_id) as num", "owner_user_id");
            wrapper.isNotNull("owner_user_id").eq("status", 1);
            wrapper.in("student_id", ids).groupBy("owner_user_id");
            List<Map<String, Object>> maps = listMaps(wrapper);
            for (Map<String, Object> map : maps) {
                boolean b = crmCustomerSettingService.queryCustomerSettingNum(2, (Long) map.get("ownerUserId"), TypeUtils.castToInt(map.get("num")));
                if (!b) {
                    throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_LOCK_MAX_ERROR);
                }
            }
        }
        actionRecordUtil.addIsLockRecord(ids, CrmEnum.STUDENT, status);
        lambdaUpdate().set(CrmStudent::getStatus, status).in(CrmStudent::getStudentId, ids).update();
        updateField("status", status, ids.stream().map(Integer::valueOf).collect(Collectors.toList()));
    }

    @Override
    public List<SimpleCrmEntity> querySimpleEntity(List<Integer> ids) {
        if (ids.size() == 0) {
            return new ArrayList<>();
        }
        List<CrmStudent> list = query().in("student_id", ids).list();
        return list.stream().map(crmCustomer -> {
            SimpleCrmEntity simpleCrmEntity = new SimpleCrmEntity();
            simpleCrmEntity.setId(crmCustomer.getStudentId());
            simpleCrmEntity.setName(crmCustomer.getCustomerName());
            return simpleCrmEntity;
        }).collect(Collectors.toList());
    }

    @Override
    public List<SimpleCrmEntity> queryByNameCustomerInfo(String name) {
        List<CrmStudent> list = query().like("customer_name", name).list();
        return list.stream().map(crmCustomer -> {
            SimpleCrmEntity simpleCrmEntity = new SimpleCrmEntity();
            simpleCrmEntity.setId(crmCustomer.getStudentId());
            simpleCrmEntity.setName(crmCustomer.getCustomerName());
            return simpleCrmEntity;
        }).collect(Collectors.toList());
    }

    @Override
    public List<SimpleCrmEntity> queryNameCustomerInfo(String name) {
        List<CrmStudent> list = query().select("student_id", "customer_name").eq("customer_name", name).list();
        return list.stream().map(crmCustomer -> {
            SimpleCrmEntity simpleCrmEntity = new SimpleCrmEntity();
            simpleCrmEntity.setId(crmCustomer.getStudentId());
            simpleCrmEntity.setName(crmCustomer.getCustomerName());
            return simpleCrmEntity;
        }).collect(Collectors.toList());
    }

    /**
     * 跟进客户名称查询客户
     *
     * @param name name
     * @return data
     */
    @Override
    public SimpleCrmEntity queryFirstCustomerByName(String name) {
        CrmStudent crmCustomer = query().select("student_id", "customer_name").eq("customer_name", name).eq("status", 1).one();
        if (crmCustomer != null) {
            SimpleCrmEntity simpleCrmEntity = new SimpleCrmEntity();
            simpleCrmEntity.setId(crmCustomer.getStudentId());
            simpleCrmEntity.setName(crmCustomer.getCustomerName());
            return simpleCrmEntity;
        } else {
            return null;
        }
    }

    /**
     * 跟进客户编号查询客户
     *
     * @param num name
     * @return data
     */
    @Override
    public SimpleCrmEntity queryCustomerByNum(String num) {
        QueryWrapper<CrmStudent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("serial_number", num);
        queryWrapper.eq("status", 1);
        CrmStudent crmCustomer = getOne(queryWrapper);
//        CrmCustomer crmCustomer = query().select("customer_id", "customer_name").eq("serial_number", num).eq("status", 1).one();
        if (crmCustomer != null) {
            SimpleCrmEntity simpleCrmEntity = new SimpleCrmEntity();
            simpleCrmEntity.setId(crmCustomer.getStudentId());
            simpleCrmEntity.setName(crmCustomer.getCustomerName());
            return simpleCrmEntity;
        } else {
            return null;
        }
    }

    /**
     * 查询文件数量
     *
     * @param customerId id
     * @return data
     */
    @Override
    public CrmInfoNumVO num(Integer customerId) {
        CrmStudent customer = getById(customerId);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        List<CrmField> crmFields = crmFieldService.queryFileField();
        List<String> batchIdList = new ArrayList<>();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmStudentData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmStudentData::getValue);
            wrapper.eq(CrmStudentData::getBatchId, customer.getBatchId());
            wrapper.in(CrmStudentData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            batchIdList.addAll(crmStudentDataService.listObjs(wrapper, Object::toString));
        }
        batchIdList.add(customer.getBatchId());
        batchIdList.addAll(crmActivityService.queryFileBatchId(customer.getStudentId(), getLabel().getType()));
        String businessCon = AuthUtil.getCrmAuthSql(CrmEnum.BUSINESS, 1);
        String contractCon = AuthUtil.getCrmAuthSql(CrmEnum.CONTRACT, 1);
        String receivablesCon = AuthUtil.getCrmAuthSql(CrmEnum.RECEIVABLES, 1);
        String refundCon = AuthUtil.getCrmAuthSql(CrmEnum.REFUND, 1);
        String contactsCon = AuthUtil.getCrmAuthSql(CrmEnum.CONTACTS, 1);
        String returnVisitCon = AuthUtil.getCrmAuthSql(CrmEnum.RETURN_VISIT, 1);
        String invoiceCon = AuthUtil.getCrmAuthSql(CrmEnum.INVOICE, 1);
        Map<String, Object> map = new HashMap<>();
        map.put("businessCon", businessCon);
        map.put("contractCon", contractCon);
        map.put("receivablesCon", receivablesCon);
        map.put("refundCon", refundCon);
        map.put("contactsCon", contactsCon);
        map.put("returnVisitCon", returnVisitCon);
        map.put("invoiceCon", invoiceCon);
        map.put("customerId", customerId);
        CrmInfoNumVO infoNumVO = getBaseMapper().queryNum(map);
        infoNumVO.setFileCount(fileService.queryNum(batchIdList));
        Set<String> member = new HashSet<>();
        member.addAll(StrUtil.splitTrim(customer.getRoUserId(), Const.SEPARATOR));
        member.addAll(StrUtil.splitTrim(customer.getRwUserId(), Const.SEPARATOR));
        if (customer.getOwnerUserId() != null) {
            member.add(customer.getOwnerUserId().toString());
        }
        infoNumVO.setMemberCount(member.size());
        return infoNumVO;
    }

    /**
     * 查询文件列表
     *
     * @param customerId id
     * @return file
     */
    @Override
    public List<FileEntity> queryFileList(Integer customerId) {
        List<FileEntity> fileEntityList = new ArrayList<>();
        CrmStudent crmCustomer = getById(customerId);
        boolean auth = AuthUtil.isRwAuth(customerId, CrmEnum.STUDENT);

        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        fileService.queryFileList(crmCustomer.getBatchId()).forEach(fileEntity -> {
            fileEntity.setSource("附件上传");
            if (auth && !fileEntity.getCreateUserId().equals(UserUtil.getUserId())) {
                fileEntity.setReadOnly(1);
            } else {
                fileEntity.setReadOnly(0);
            }
            fileEntityList.add(fileEntity);
        });
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmStudentData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmStudentData::getValue);
            wrapper.eq(CrmStudentData::getBatchId, crmCustomer.getBatchId());
            wrapper.in(CrmStudentData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            List<FileEntity> data = fileService.queryFileList(crmStudentDataService.listObjs(wrapper, Object::toString));
            data.forEach(fileEntity -> {
                fileEntity.setSource("客户详情");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        List<String> stringList = crmActivityService.queryFileBatchId(crmCustomer.getStudentId(), getLabel().getType());
        if (stringList.size() > 0) {
            List<FileEntity> data = fileService.queryFileList(stringList);
            data.forEach(fileEntity -> {
                fileEntity.setSource("跟进记录");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        return fileEntityList;
    }


    /**
     * 获取客户名称
     *
     * @param customerId id
     * @return data
     */
    @Override
    public String getCustomerName(Integer customerId) {
        if (customerId == null) {
            return "";
        }
        return lambdaQuery().select(CrmStudent::getCustomerName).eq(CrmStudent::getStudentId, customerId)
                .oneOpt().map(CrmStudent::getCustomerName).orElse("");
    }


    /**
     * 团队成员相关消息
     */
    @Override
    public void addTermMessage(AdminMessageEnum messageEnum, Integer typeId, String title, Long userId) {
        AdminMessageBO adminMessageBO = new AdminMessageBO();
        adminMessageBO.setTitle(title);
        adminMessageBO.setTypeId(typeId);
        adminMessageBO.setUserId(UserUtil.getUserId());
        adminMessageBO.setIds(Collections.singletonList(userId));
        adminMessageBO.setMessageType(messageEnum.getType());
        SpringUtils.getBean(AdminMessageService.class).sendMessage(adminMessageBO);
    }

    /**
     * 大的搜索框的搜索字段
     *
     * @return fields
     */
    @Override
    public String[] appendSearch() {
        return new String[]{"customerName", "telephone", "wechat"};
    }

    /**
     * 获取crm列表类型
     *
     * @return data
     */
    @Override
    public CrmEnum getLabel() {
        return CrmEnum.STUDENT;
    }

    /**
     * 查询所有字段
     *
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryDefaultField() {
        List<CrmModelFiledVO> filedList = crmFieldService.queryField(getLabel().getType());

//        filedList.removeIf(field -> field.getFieldName().equals("sellOwnerId"));
//        filedList.removeIf(field -> field.getFieldName().equals("sellOwnerName"));

        filedList.add(new CrmModelFiledVO("lastTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("lastContent", FieldEnum.TEXTAREA, 1));
        filedList.add(new CrmModelFiledVO("updateTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("dealTime", FieldEnum.DATETIME, "成交时间", 1));
        filedList.add(new CrmModelFiledVO("receiveTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("poolTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("createTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("roUserId", FieldEnum.CHECKBOX, 1));
        filedList.add(new CrmModelFiledVO("rwUserId", FieldEnum.CHECKBOX, 1));
        filedList.add(new CrmModelFiledVO("ownerUserId", FieldEnum.USER, 1));
        filedList.add(new CrmModelFiledVO("createUserId", FieldEnum.USER, 1));
        filedList.add(new CrmModelFiledVO("status", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("ownerUserName", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("createUserName", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("serialNumber", FieldEnum.TEXT,1));
//        filedList.add(new CrmModelFiledVO("dataFrom", FieldEnum.TEXT,1));
//        filedList.add(new CrmModelFiledVO("sellOwnerId", FieldEnum.USER,1));
//        filedList.add(new CrmModelFiledVO("sellOwnerName", FieldEnum.TEXT,1));
        filedList.add(new CrmModelFiledVO("assistantUserId", FieldEnum.TEXT,1));
        filedList.add(new CrmModelFiledVO("assistantUserName", FieldEnum.TEXT,1));
        filedList.add(new CrmModelFiledVO("ownerDeptName", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("ownerDeptId", FieldEnum.STRUCTURE, 1));
        return filedList;
    }

    @Override
    public boolean isMaxOwner(Long ownerUserId, List<Integer> ids) {
        Integer number = getBaseMapper().ownerNum(ids, ownerUserId);
        return crmCustomerSettingService.queryCustomerSettingNum(1, ownerUserId, number);
    }


    @Override
    public void updateInformation(CrmUpdateInformationBO updateInformationBO) {
        String batchId = updateInformationBO.getBatchId();
        Integer customerId = updateInformationBO.getId();
        if (!UserUtil.isAdmin() && getBaseMapper().queryIsRoUser(customerId, UserUtil.getUserId()) > 0) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
        }
        updateInformationBO.getList().forEach(record -> {
            CrmStudent oldCustomer = getById(customerId);
            Map<String, Object> oldCustomerMap = BeanUtil.beanToMap(oldCustomer);
            if (record.getInteger("fieldType") == 1) {
                Map<String, Object> crmCustomerMap = new HashMap<>(oldCustomerMap);
                crmCustomerMap.put(record.getString("fieldName"), record.get("value"));
                CrmStudent crmCustomer = BeanUtil.mapToBean(crmCustomerMap, CrmStudent.class, true);

                // 回款审批中及审批通过不允许编辑客户信息
                Integer receivables = crmReceivablesService.queryCountReceivablesByCustomerId(crmCustomer.getStudentId());
                if(receivables > 0){
                    if((oldCustomer.getTelephone() == null && crmCustomer.getTelephone() != null) ||
                            (oldCustomer.getTelephone() != null && crmCustomer.getTelephone() == null) ||
                            (StringUtil.isNotEmpty(oldCustomer.getTelephone()) && StringUtil.isNotEmpty(crmCustomer.getTelephone()) && (!crmCustomer.getTelephone().equals(oldCustomer.getTelephone())))){
                        throw new CrmException(CrmCodeEnum.CRM_CUSTOMER_HAVE_RECEIVABLES);
                    }
                }

                actionRecordUtil.updateRecord(oldCustomerMap, crmCustomerMap, CrmEnum.STUDENT, crmCustomer.getCustomerName(), crmCustomer.getStudentId());
                update().set(StrUtil.toUnderlineCase(record.getString("fieldName")), record.get("value")).eq("student_id", updateInformationBO.getId()).update();
                if("assistantUserId".equals(record.getString("fieldName"))){
                    Long userId = Long.parseLong(record.getString("value"));
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("fieldName","assistantUserName");
                    jsonObject.put("type",1);
                    jsonObject.put("formType","text");
                    jsonObject.put("fieldType",1);
                    jsonObject.put("value",UserCacheUtil.getUserName(userId));
                    updateField(jsonObject, customerId);

                    if(!ObjectUtil.equal(oldCustomer.getAssistantUserId(),record.getLong("value"))){
                        String assistantUserName = UserCacheUtil.getUserName(record.getLong("value"));
                        if (!UserUtil.getUserId().equals(oldCustomer.getAssistantUserId())) {
                            if (oldCustomer.getAssistantUserId() != null) {
                                addMessage(oldCustomer.getCustomerName(), assistantUserName, oldCustomer.getAssistantUserId(), AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(), crmCustomer.getStudentId());
                            }
                        }
                        if (record.getLong("value") != null) {
                            addMessage(oldCustomer.getCustomerName(), assistantUserName, record.getLong("value"), AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(), crmCustomer.getStudentId());
                        }
                    }
                }

                if("ownerUserId".equals(record.getString("fieldName"))){
                    String deptName = "";
                    Integer deptId = null;
                    if(BeanUtil.isNotEmpty(record.get("value"))){
                        deptName = this.adminService.queryDeptName(Integer.valueOf(String.valueOf(record.get("value"))));
                        deptId = adminService.getUserInfo(Long.valueOf(String.valueOf(record.get("value")))).getDeptId();
                    }
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("fieldName","ownerDeptId");
                    jsonObject.put("value", deptId);
                    jsonObject.put("type",2);
                    jsonObject.put("fieldType",1);
                    update().set(StrUtil.toUnderlineCase("ownerDeptId"), deptId).eq("student_id",updateInformationBO.getId()).update();
                    updateField(jsonObject, customerId);

                    JSONObject deptNamejsonObject = new JSONObject();
                    deptNamejsonObject.put("fieldName","ownerDeptName");
                    deptNamejsonObject.put("value",deptName);
                    deptNamejsonObject.put("type",2);
                    deptNamejsonObject.put("fieldType",1);
                    updateField(deptNamejsonObject, customerId);

                    getRestTemplate().refresh(getIndex());
                }

                if ("customerName".equals(record.getString("fieldName"))) {
                    ElasticUtil.batchUpdateEsData(elasticsearchRestTemplate.getClient(), "student", crmCustomer.getStudentId().toString(), crmCustomer.getCustomerName());
                }
            } else if (record.getInteger("fieldType") == 0 || record.getInteger("fieldType") == 2) {
                CrmStudentData customerData = crmStudentDataService.lambdaQuery().select(CrmStudentData::getValue).eq(CrmStudentData::getFieldId, record.getInteger("fieldId"))
                        .eq(CrmStudentData::getBatchId, batchId).last("limit 1").one();
                String value = customerData != null ? customerData.getValue() : null;
                String detail = actionRecordUtil.getDetailByFormTypeAndValue(record,value);

                boolean isUpdate = false;
                if ((null == value && null == record.get("value"))) {
                    isUpdate = false;
                } else if (null != value && !value.equals(String.valueOf(record.get("value")))) {
                    isUpdate = true;
                } else if (null != record.get("value") && !String.valueOf(record.get("value")).equals(value)) {
                    isUpdate = true;
                }

                if (isUpdate){
                    //记录操作日志
                    actionRecordUtil.publicContentRecord(CrmEnum.STUDENT, BehaviorEnum.UPDATE, customerId, oldCustomer.getCustomerName(), detail);
                    boolean bol = crmStudentDataService.lambdaUpdate()
                            .set(CrmStudentData::getName, record.getString("fieldName"))
                            .set(CrmStudentData::getValue, record.getString("value"))
                            .eq(CrmStudentData::getFieldId, record.getInteger("fieldId"))
                            .eq(CrmStudentData::getBatchId, batchId).update();
                    if (!bol) {
                        CrmStudentData crmStudentData = new CrmStudentData();
                        crmStudentData.setFieldId(record.getInteger("fieldId"));
                        crmStudentData.setName(record.getString("fieldName"));
                        crmStudentData.setValue(record.getString("value"));
                        crmStudentData.setCreateTime(DateUtil.date());
                        crmStudentData.setBatchId(batchId);
                        crmStudentDataService.save(crmStudentData);
                    }
                }
            }
            updateField(record, customerId);

        });
    }

    @Override
    public List<CrmDataCheckVO> dataCheck(CrmDataCheckBO dataCheckBO) {
        List<CrmDataCheckVO> list = getBaseMapper().dataCheck(dataCheckBO);
        for (CrmDataCheckVO crmDataCheckVO : list) {
            if (StrUtil.isNotEmpty(crmDataCheckVO.getPoolIds())){
                List<String> poolIds = StrUtil.splitTrim(crmDataCheckVO.getPoolIds(), Const.SEPARATOR);
                List<Integer> poolIdList = poolIds.stream().map(Integer::valueOf).collect(Collectors.toList());
                crmDataCheckVO.setPoolAuthList(crmCustomerPoolService.getOnePoolAuthByPoolIds(poolIdList));
            }
            if (crmDataCheckVO.getOwnerUserId() != null) {
                crmDataCheckVO.setOwnerUserName(UserCacheUtil.getUserName(crmDataCheckVO.getOwnerUserId()));
            }
            if (crmDataCheckVO.getContactsId() != null) {
                crmDataCheckVO.setContactsName(Optional.ofNullable(crmContactsService.getById(crmDataCheckVO.getContactsId())).map(CrmContacts::getName).orElse(null));
            }
        }
        return list;
    }

    @Override
    public BasePage<JSONObject> queryReceivablesPlan(CrmRelationPageBO crmRelationPageBO) {
        String conditions = AuthUtil.getCrmAuthSql(CrmEnum.CONTRACT, "c", 1);
        return getBaseMapper().queryReceivablesPlan(crmRelationPageBO.parse(), crmRelationPageBO.getCustomerId(), conditions);
    }

    @Override
    public BasePage<JSONObject> queryReceivables(CrmRelationPageBO crmRelationPageBO) {
        String conditions = AuthUtil.getCrmAuthSql(CrmEnum.RECEIVABLES, "a", 1);
        BasePage<JSONObject> jsonObjects = getBaseMapper().queryReceivables(crmRelationPageBO.parse(), crmRelationPageBO.getCustomerId(),crmRelationPageBO.getDefaultGenerate(), conditions);
        for (JSONObject jsonObject : jsonObjects.getList()) {
            String ownerUserName = UserCacheUtil.getUserName(jsonObject.getLong("ownerUserId"));
            jsonObject.put("ownerUserName", ownerUserName);
        }
        return jsonObjects;
    }

    @Override
    public BasePage<JSONObject> queryRefund(CrmRelationPageBO crmRelationPageBO) {
        String conditions = AuthUtil.getCrmAuthSql(CrmEnum.REFUND, "a", 1);
        BasePage<JSONObject> jsonObjects = getBaseMapper().queryRefund(crmRelationPageBO.parse(), crmRelationPageBO.getCustomerId(), conditions);
        for (JSONObject jsonObject : jsonObjects.getList()) {
            String ownerUserName = UserCacheUtil.getUserName(jsonObject.getLong("ownerUserId"));
            jsonObject.put("ownerUserName", ownerUserName);
        }
        return jsonObjects;
    }

    @Override
    public BasePage<JSONObject> queryReturnVisit(CrmRelationPageBO crmRelationPageBO) {
        List<CrmField> nameList = crmFieldService.lambdaQuery().select(CrmField::getFieldId, CrmField::getFieldName).eq(CrmField::getLabel, CrmEnum.RETURN_VISIT.getType())
                .eq(CrmField::getIsHidden, 0).ne(CrmField::getFieldType, 1).list();
        String conditions = AuthUtil.getCrmAuthSql(CrmEnum.RETURN_VISIT, "a", 1);
        BasePage<JSONObject> jsonObjects = getBaseMapper().queryReturnVisit(crmRelationPageBO.parse(), crmRelationPageBO.getCustomerId(), conditions, nameList);
        for (JSONObject jsonObject : jsonObjects.getList()) {
            String ownerUserName = UserCacheUtil.getUserName(jsonObject.getLong("ownerUserId"));
            jsonObject.put("ownerUserName", ownerUserName);
        }
        return jsonObjects;
    }

    @Override
    public BasePage<JSONObject> queryInvoice(CrmRelationPageBO crmRelationPageBO) {
        String conditions = AuthUtil.getCrmAuthSql(CrmEnum.INVOICE, "a", 0);
        BasePage<JSONObject> jsonObjects = getBaseMapper().queryInvoice(crmRelationPageBO.parse(), crmRelationPageBO.getCustomerId(), conditions);
        for (JSONObject jsonObject : jsonObjects.getList()) {
            String ownerUserName = UserCacheUtil.getUserName(jsonObject.getLong("ownerUserId"));
            jsonObject.put("ownerUserName", ownerUserName);
        }
        return jsonObjects;
    }

    @Override
    public BasePage<JSONObject> queryInvoiceInfo(CrmRelationPageBO crmRelationPageBO) {
        BasePage<JSONObject> jsonObjects = getBaseMapper().queryInvoiceInfo(crmRelationPageBO.parse(), crmRelationPageBO.getCustomerId());
        for (JSONObject jsonObject : jsonObjects.getList()) {
            String ownerUserName = UserCacheUtil.getUserName(jsonObject.getLong("ownerUserId"));
            jsonObject.put("ownerUserName", ownerUserName);
        }
        return jsonObjects;
    }

    @Override
    public BasePage<JSONObject> queryCallRecord(CrmRelationPageBO crmRelationPageBO) {
        BasePage<JSONObject> jsonObjects = getBaseMapper().queryCallRecord(crmRelationPageBO.parse(), crmRelationPageBO.getCustomerId());
        for (JSONObject jsonObject : jsonObjects.getList()) {
            String ownerUserName = UserCacheUtil.getUserName(jsonObject.getLong("ownerUserId"));
            jsonObject.put("ownerUserName", ownerUserName);
        }
        return jsonObjects;
    }


    @Override
    public List<JSONObject> nearbyCustomer(String lng, String lat, Integer type, Integer radius, Long ownerUserId) {
        Integer menuId = adminService.queryMenuId("crm", "customer", "nearbyCustomer");
        List<Long> authUserIdList = AuthUtil.getUserIdByAuth(menuId);
        List<Integer> poolIdList = new ArrayList<>();
        if (ObjectUtil.isEmpty(type) || type.equals(9)) {
            if (UserUtil.isAdmin()) {
                poolIdList = crmCustomerPoolService.lambdaQuery().select(CrmCustomerPool::getPoolId).list().stream().map(CrmCustomerPool::getPoolId).collect(Collectors.toList());
            } else {
                poolIdList = crmCustomerPoolService.queryPoolIdByUserId();
            }
        }
        List<JSONObject> jsonObjects = getBaseMapper().nearbyCustomer(lng, lat, type, radius, ownerUserId, authUserIdList, poolIdList);
        for (JSONObject jsonObject : jsonObjects) {
            String ownerUserName = UserCacheUtil.getUserName(jsonObject.getLong("ownerUserId"));
            jsonObject.put("ownerUserName", ownerUserName);
        }
        return jsonObjects;
    }

    @Override
    public List<String> eventCustomer(CrmEventBO crmEventBO) {
        return getBaseMapper().eventCustomer(crmEventBO);
    }

    @Override
    public BasePage<Map<String, Object>> eventCustomerPageList(QueryEventCrmPageBO eventCrmPageBO) {
        Long userId = eventCrmPageBO.getUserId();
        Long time = eventCrmPageBO.getTime();
        if (userId == null) {
            userId = UserUtil.getUserId();
        }
        List<Integer> customerIds = getBaseMapper().eventCustomerList(userId, new Date(time));
        if (customerIds.size() == 0) {
            return new BasePage<>();
        }
        List<String> collect = customerIds.stream().map(Object::toString).collect(Collectors.toList());
        CrmSearchBO crmSearchBO = new CrmSearchBO();
        crmSearchBO.setSearchList(Collections.singletonList(new CrmSearchBO.Search("_id", "id", CrmSearchBO.FieldSearchEnum.ID, collect)));
        crmSearchBO.setLabel(CrmEnum.STUDENT.getType());
        crmSearchBO.setPage(eventCrmPageBO.getPage());
        crmSearchBO.setLimit(eventCrmPageBO.getLimit());
        BasePage<Map<String, Object>> page = queryPageList(crmSearchBO);
        return page;
    }

    @Override
    public List<Integer> forgottenCustomer(Integer day, List<Long> userIds, String search) {
        return getBaseMapper().forgottenCustomer(day, userIds, search);
    }

    @Override
    public List<Integer> unContactCustomer(String search, List<Long> userIds) {
        return getBaseMapper().unContactCustomer(search, userIds);
    }

    @Override
    public String generateNo(LocalDate date) {
        String dateStr = date.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String nextNo = getBaseMapper().getNextNo(dateStr);
        if (nextNo == null) {
            return dateStr + "000000";
        }
        return nextNo;
    }

    public Integer initStudent(CrmStudent crmStudent){

//        QueryWrapper<BillCrmStudentPool> queryWrapper = new QueryWrapper<BillCrmStudentPool>();
//        queryWrapper.eq("status", 1);
//        BillCrmStudentPool studentPool = crmStudentPoolService.getBaseMapper().selectOne(queryWrapper);
//        Long studentPoolId = studentPool.getStudentPoolId();
//        crmStudent.setStudentPoolId(studentPoolId);
        crmStudent.setCreateTime(new Date());
        crmStudent.setUpdateTime(new Date());
        crmStudent.setDrawTime(null);
        save(crmStudent);

        CrmModelSaveBO crmModelSaveBO = new CrmModelSaveBO();
        crmModelSaveBO.setEntity(BeanUtil.beanToMap(crmStudent));

        savePage(crmModelSaveBO, crmStudent.getStudentId(),false);

        return crmStudent.getStudentId();
    }

    /**
     * 分配VIP学员
     * @param changeUserBO
     */
    @Override
    public void distributionStudent(CrmBillStudentPoolChangeUserBO changeUserBO){
        if (!Optional.ofNullable(changeUserBO.getAssistantUserId()).isPresent()
                || !Optional.ofNullable(changeUserBO.getIds()).isPresent()) {
            throw new CrmException(CrmCodeEnum.CRM_ERROR_PARAMETER_REQUIRED);
        }

        // 根据VIP学员池配置查看当前用户是否有权限查看列表数据
        QueryWrapper<BillCrmStudentPool> queryWrapper = new QueryWrapper<BillCrmStudentPool>();
        queryWrapper.eq("status", 1);
        BillCrmStudentPool studentPool = crmStudentPoolService.getBaseMapper().selectOne(queryWrapper);
        List<String> roleIds = Arrays.asList(studentPool.getMemberUserId().split(","));
        List<String> deptIds = Arrays.asList(studentPool.getMemberDeptId().split(","));

        List<Integer> roles = UserUtil.getUser().getRoles();
        List<String> roleIdsToStr = roles.stream().map(Object::toString).collect(Collectors.toList());

        List<Integer> allDeptIds = new ArrayList<>();
        for(String deptId : deptIds){
            allDeptIds.addAll(SpringUtils.getBean(IAdminDeptService.class).queryChildDept(Integer.valueOf(deptId)));
            allDeptIds.add(Integer.valueOf(deptId));
        }

        if(((!allDeptIds.contains(UserUtil.getUser().getDeptId())) && (!UserUtil.isAdmin())) || ((!isContains(roleIds, roleIdsToStr)) && (!UserUtil.isAdmin()))){
            throw new CrmException(CrmCodeEnum.CRM_NO_AUTH_DISTRIBUTION);
        }
        if(CollectionUtil.isNotEmpty(changeUserBO.getIds())){
            for(int i = 0;i < changeUserBO.getIds().size();i++){
                SpringUtils.getBean(ICrmStudentService.class).fenPeiVipStudent(changeUserBO.getIds().get(i), changeUserBO);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void fenPeiVipStudent(Integer id, CrmBillStudentPoolChangeUserBO changeUserBO){

        String key = Constants.RECEIVE_STUDENT + id;
        String value = UUID.randomUUID().toString();

        //加锁
        boolean b = redisCache.lock(key, value, 10, TimeUnit.SECONDS);
        if (!b) {
            throw new CrmException(CrmCodeEnum.BUSINESS_LOCK_DATA);
        }
        try {

            CrmStudent student = getById(id);

            if(ObjectUtil.isNotEmpty(student.getAssistantUserId())){
                throw new CrmException(CrmCodeEnum.STUDENT_IS_RECEIVE);
            }

            student.setAssistantUserId(changeUserBO.getAssistantUserId());
            student.setDrawTime(DateUtils.getNowDate());
            update(student, new UpdateWrapper<CrmStudent>().lambda().set(CrmStudent::getStudentPoolId,null).eq(CrmStudent::getStudentId,student.getStudentId()));

            // 更新学员中助教协作人
            CrmCustomer customer = crmCustomerService.queryCustomerBySerialNumber(student.getSerialNumber());
            customer.setAssistantUserId(String.valueOf(changeUserBO.getAssistantUserId()));
            crmCustomerService.updateById(customer);

            Map<String, Object> updateMap = new HashMap<>();
            updateMap.put("assistantUserId",changeUserBO.getAssistantUserId());
            updateMap.put("studentPoolId",null);
            updateMap.put("drawTime",DateUtil.formatDateTime(new Date()));
            ElasticUtil.updateField(elasticsearchRestTemplate, updateMap, id, CrmEnum.STUDENT.getIndex());

            Map<String, Object> customerMap = new HashMap<>();
            customerMap.put("assistantUserId", changeUserBO.getAssistantUserId());
            ElasticUtil.updateField(elasticsearchRestTemplate, customerMap, customer.getCustomerId(), CrmEnum.CUSTOMER.getIndex());

            // 分配VIP学员新增消息
            if(changeUserBO.getAssistantUserId() != null){
                addMessage(student.getCustomerName(),"VIP学员 " + student.getCustomerName() + " 分配成功",changeUserBO.getAssistantUserId(),AdminMessageEnum.CRM_VIP_STUDENT_ALLOCATION.getType(),student.getStudentId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            redisCache.unlock(key, value);
        }


    }

    public static boolean isContains(List<String> oneList,List<String> otherList){
        for(String other : otherList){
            if(oneList.contains(other)){
                return true;
            }
        }
        return false;
    }


    /**
     * 领取VIP学员
     * @param changeUserBO
     */
    @Override
    public void receiveStudent(CrmBillStudentPoolChangeUserBO changeUserBO){
        if (!Optional.ofNullable(changeUserBO.getAssistantUserId()).isPresent()
                || !Optional.ofNullable(changeUserBO.getValidType()).isPresent()
                || !Optional.ofNullable(changeUserBO.getIds()).isPresent()) {
            throw new CrmException(CrmCodeEnum.CRM_ERROR_PARAMETER_REQUIRED);
        }

        // 根据VIP学员池配置查看当前用户是否有权限查看列表数据
        QueryWrapper<BillCrmStudentPool> queryWrapper = new QueryWrapper<BillCrmStudentPool>();
        queryWrapper.eq("status", 1);
        BillCrmStudentPool studentPool = crmStudentPoolService.getBaseMapper().selectOne(queryWrapper);
        List<String> deptIds = Arrays.asList(studentPool.getMemberDeptId().split(","));

        List<Integer> allDeptIds = new ArrayList<>();
        for(String deptId : deptIds){
            allDeptIds.addAll(SpringUtils.getBean(IAdminDeptService.class).queryChildDept(Integer.valueOf(deptId)));
            allDeptIds.add(Integer.valueOf(deptId));
        }

        if((!allDeptIds.contains(UserUtil.getUser().getDeptId())) && (!UserUtil.isAdmin())){
            throw new CrmException(CrmCodeEnum.CRM_NO_AUTH_RECEIVE);
        }
        if(CollectionUtil.isNotEmpty(changeUserBO.getIds())){
            for(int i = 0;i < changeUserBO.getIds().size();i++){
                SpringUtils.getBean(ICrmStudentService.class).lingQuVipStudent(changeUserBO.getIds().get(i), changeUserBO);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void lingQuVipStudent(Integer id, CrmBillStudentPoolChangeUserBO changeUserBO){
        String key = Constants.RECEIVE_STUDENT + id;
        String value = UUID.randomUUID().toString();
        //加锁
        boolean b = redisCache.lock(key, value, 10, TimeUnit.SECONDS);
        if (!b) {
            throw new CrmException(CrmCodeEnum.BUSINESS_LOCK_DATA);
        }
        try {

            CrmStudent student = getById(id);

            if(ObjectUtil.isNotEmpty(student.getAssistantUserId())){
                throw new CrmException(CrmCodeEnum.STUDENT_IS_RECEIVE);
            }

            if(new Integer(0).equals(changeUserBO.getValidType())){
                if (!Optional.ofNullable(changeUserBO.getPhone()).isPresent()){
                    throw new CrmException(CrmCodeEnum.CRM_ERROR_PARAMETER_REQUIRED);
                }
                if(!changeUserBO.getPhone().equals(student.getTelephone())){
                    throw new CrmException(CrmCodeEnum.CRM_STUDENT_POLL_PHONE);
                }
            }else{
                if (!Optional.ofNullable(changeUserBO.getWechat()).isPresent()){
                    throw new CrmException(CrmCodeEnum.CRM_ERROR_PARAMETER_REQUIRED);
                }
                if(!changeUserBO.getWechat().equals(student.getWechat())){
                    throw new CrmException(CrmCodeEnum.CRM_STUDENT_POLL_WECHAT);
                }
            }

            student.setAssistantUserId(changeUserBO.getAssistantUserId());
            student.setDrawTime(DateUtils.getNowDate());
            update(student, new UpdateWrapper<CrmStudent>().lambda().set(CrmStudent::getStudentPoolId,null).eq(CrmStudent::getStudentId,student.getStudentId()));

            CrmCustomer customer = crmCustomerService.queryCustomerBySerialNumber(student.getSerialNumber());
            customer.setAssistantUserId(String.valueOf(changeUserBO.getAssistantUserId()));
            crmCustomerService.updateById(customer);

            Map<String, Object> updateMap = new HashMap<>();
            updateMap.put("assistantUserId", changeUserBO.getAssistantUserId());
            updateMap.put("studentPoolId", null);
            updateMap.put("drawTime", DateUtil.formatDateTime(new Date()));
            ElasticUtil.updateField(elasticsearchRestTemplate, updateMap, student.getStudentId(), CrmEnum.STUDENT.getIndex());

            Map<String, Object> customerMap = new HashMap<>();
            customerMap.put("assistantUserId", changeUserBO.getAssistantUserId());
            ElasticUtil.updateField(elasticsearchRestTemplate, customerMap, customer.getCustomerId(), CrmEnum.CUSTOMER.getIndex());
//            updateField(updateMap, Collections.singletonList(id));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            redisCache.unlock(key, value);
        }
    }


    /**
     * 删除客户数据
     *
     * @param serialNumbers 系统编号
     */
    @Override
    public void deleteBySerialNumbers(List<String> serialNumbers) {

        List<CrmStudent> studentList = lambdaQuery().select(CrmStudent::getStudentId).in(CrmStudent::getSerialNumber, serialNumbers).list();
        List<Integer> ids = studentList.stream().map(CrmStudent::getStudentId).collect(Collectors.toList());

        lambdaUpdate().set(CrmStudent::getUpdateTime, new Date()).set(CrmStudent::getStatus, 3).in(CrmStudent::getStudentId, ids).update();
        LambdaQueryWrapper<CrmStudent> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CrmStudent::getStudentId, ids);
        List<String> batchList = listObjs(wrapper, Object::toString);
        //删除文件
        adminFileService.delete(batchList);
        //删除跟进记录
        crmActivityService.deleteActivityRecord(CrmActivityEnum.STUDENT, ids);
        //删除字段操作记录
        crmActionRecordService.deleteActionRecord(CrmEnum.STUDENT, ids);
        //删除自定义字段
        crmStudentDataService.deleteByBatchId(batchList);
        deletePage(ids);

    }

    /**
     * 根据系统编号查询VIP学员信息
     * @param serialNumber
     * @return
     */
    @Override
    public CrmStudent queryStudentBySerialNumber(String serialNumber){
        return baseMapper.queryCustomerBySerialNumber(serialNumber);
    }

    public List<CrmStudent> queryStudentByTelephone(String telephone){
        return baseMapper.queryStudentsByTelephone(telephone);
    }

    public List<CrmStudent> queryStudentsByWechat(String wechat){
        return baseMapper.queryStudentsByWechat(wechat);
    }

    /**
     * 修改VIP学员助教协作人
     * @param changeUserBO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeAssistantUser(CrmBillStudentPoolChangeUserBO changeUserBO) {

        QueryWrapper<CrmStudent> studentQueryWrapper = new QueryWrapper<>();
        studentQueryWrapper.in("student_id",changeUserBO.getIds());
        List<CrmStudent> studentList = getBaseMapper().selectList(studentQueryWrapper);

        LambdaUpdateWrapper<CrmStudent> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CrmStudent::getStudentId,changeUserBO.getIds());
        wrapper.set(CrmStudent::getAssistantUserId,changeUserBO.getAssistantUserId());
        update(wrapper);

        LambdaQueryWrapper<CrmStudent> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(CrmStudent::getSerialNumber);
        lambdaQueryWrapper.in(CrmStudent::getStudentId,changeUserBO.getIds());
        List<String> serialNumberList = listObjs(lambdaQueryWrapper,Object::toString);

        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("serial_number",serialNumberList);
        queryWrapper.notIn("status",3);
        List<CrmCustomer> customerList = crmCustomerService.getBaseMapper().selectList(queryWrapper);
        List<Integer> customerIds = customerList.stream().map(CrmCustomer::getCustomerId).collect(Collectors.toList());

        if(CollectionUtil.isNotEmpty(customerIds)){
            LambdaUpdateWrapper<CrmCustomer> customerWrapper = new LambdaUpdateWrapper<>();
            customerWrapper.in(CrmCustomer::getCustomerId,customerIds);
            customerWrapper.set(CrmCustomer::getAssistantUserId,changeUserBO.getAssistantUserId());
            crmCustomerService.update(customerWrapper);
        }

        String assistanUserName = UserCacheUtil.getUserName(changeUserBO.getAssistantUserId());

        Map<String, Object> customerMap = new HashMap<>();
        customerMap.put("assistantUserId", changeUserBO.getAssistantUserId());
        customerMap.put("assistantUserName", assistanUserName);
        for(Integer customerId : customerIds){
            ElasticUtil.updateField(elasticsearchRestTemplate, customerMap, customerId, CrmEnum.CUSTOMER.getIndex());
        }

        // 更改ES
        Map<String, Object> map = new HashMap<>();
        map.put("assistantUserId", changeUserBO.getAssistantUserId());
        map.put("assistantUserName", assistanUserName);
        updateField(map, changeUserBO.getIds());

        for(CrmStudent student : studentList){
            if((!UserUtil.getUserId().equals(student.getAssistantUserId())) && (student.getAssistantUserId() != null)){
                addMessage(student.getCustomerName(),assistanUserName,student.getAssistantUserId(),AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(),student.getStudentId());
            }

            if((!UserUtil.getUserId().equals(changeUserBO.getAssistantUserId())) && changeUserBO.getAssistantUserId() != null){
                addMessage(student.getCustomerName(),assistanUserName,changeUserBO.getAssistantUserId(),AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(),student.getStudentId());
            }
        }
    }

    /**
     * 学员变更助教协作人同步修改VIP学员助教协作人
     * @param changeUserBO
     */
    @Override
    public void changeAssistantUserToCustomer(CrmBillStudentPoolChangeUserBO changeUserBO) {
        QueryWrapper<CrmStudent> studentQueryWrapper = new QueryWrapper<>();
        studentQueryWrapper.in("student_id",changeUserBO.getIds());
        List<CrmStudent> studentList = getBaseMapper().selectList(studentQueryWrapper);

        LambdaUpdateWrapper<CrmStudent> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CrmStudent::getStudentId,changeUserBO.getIds());
        wrapper.set(CrmStudent::getAssistantUserId,changeUserBO.getAssistantUserId());
        update(wrapper);

        String assistanUserName = UserCacheUtil.getUserName(changeUserBO.getAssistantUserId());

        // 更改ES
        Map<String, Object> map = new HashMap<>();
        map.put("assistantUserId", changeUserBO.getAssistantUserId());
        map.put("assistantUserName", assistanUserName);
        updateField(map, changeUserBO.getIds());

        for(CrmStudent student : studentList){
            if((!UserUtil.getUserId().equals(student.getAssistantUserId())) && (student.getAssistantUserId() != null)){
                addMessage(student.getCustomerName(),assistanUserName,student.getAssistantUserId(),AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(),student.getStudentId());
            }

            if((!UserUtil.getUserId().equals(changeUserBO.getAssistantUserId())) && changeUserBO.getAssistantUserId() != null){
                addMessage(student.getCustomerName(),assistanUserName,changeUserBO.getAssistantUserId(),AdminMessageEnum.CRM_VIP_STUDENT_CHANGE_ASSISTANTUSERID_USER.getType(),student.getStudentId());
            }
        }
    }

    /**
     * 根据Ids查询batchId
     * @param ids
     * @return
     */
    @Override
    public List<String> queryBatchIdsByIds(List<Long> ids){
        return this.baseMapper.queryBatchIdsByIds(ids);
    }

    /**
     * 更新学员状态
     * @param ids
     * @param studentStatus
     */
    @Override
    @Transactional
    public void updateStudentStatus(List<Long> ids,Integer studentStatus){
        this.baseMapper.updateStudentStatus(ids, studentStatus);

        for(Long id : ids){
            try {
                UpdateRequest request = new UpdateRequest(CrmEnum.STUDENT.getIndex(), getDocType(), id.toString());
                Map<String, Object> map = new HashMap<>();
                map.put("studentStatus", studentStatus);
                request.doc(map);
                getRestTemplate().getClient().update(request, RequestOptions.DEFAULT);
                getRestTemplate().refresh(CrmEnum.STUDENT .getIndex());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 更新风险标签
     * @param ids
     * @param riskLabel
     */
    @Override
    @Transactional
    public void updateRiskLabel(List<Integer> ids,String riskLabel){
        List<CrmStudent> customerList = query().in("student_id", ids).list();

        this.baseMapper.updateRiskLabel(ids, riskLabel);

        updateField("riskLabel", riskLabel, ids);

        for(CrmStudent student : customerList){
            if(RiskLabelEnum.NORMAL.getRemarks().equals(student.getRiskLabel()) && RiskLabelEnum.RISK.getRemarks().equals(riskLabel)){
                AdminMessageBO adminMessageBO = new AdminMessageBO();
                adminMessageBO.setTitle(student.getCustomerName());
                adminMessageBO.setTypeId(student.getStudentId());
                adminMessageBO.setUserId(UserUtil.getUserId());
                adminMessageBO.setIds(Collections.singletonList(student.getOwnerUserId()));
                adminMessageBO.setMessageType(AdminMessageEnum.CRM_CUSTOMER_CHANGE_RISK_LABEL.getType());
                ApplicationContextHolder.getBean(AdminMessageService.class).sendMessage(adminMessageBO);
            }
        }

    }
}
